⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl_cin.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
(*

cl_cin.pas created on 5-march-2002 by Skybuck Flying

converted from cl_cin.c

CHANGES:

03-jun-2002 Juha Hartikainen (juha@linearteam.org)
- Updated this to be a real unit
- Fixed conversion and language errors

06-jun-2002 Juha Hartikainen (juha@linearteam.org)
- Unit now compiles, Huff1decompress might be broken.

*)
unit cl_cin;

interface

uses q_shared, Files, SysUtils;

type
  cblock_t = record
    data: pbytearray;
    count: integer;
  end;

  cinematics_t = record
    restart_sound: qboolean;
    s_rate: integer;
    s_width: integer;
    s_channels: integer;

    width: integer;
    height: integer;
    pic: pbyte;
    pic_pending: pbyte;

    // order 1 huffman stuff
    hnodes1: pinteger; // [256][256][2];
    numhnodes1: array[0..255] of integer;

    h_used: array[0..511] of integer;
    h_count: array[0..511] of integer;
  end;

procedure SCR_PlayCinematic(arg: pchar);
function SCR_DrawCinematic: qboolean;
procedure SCR_RunCinematic;
procedure SCR_StopCinematic;
procedure SCR_FinishCinematic;

var
  cin: cinematics_t;

implementation

uses Common, qfiles, cl_main, vid_dll, snd_dma, Client, cl_scrn, cd_win,
  CPas, CVar, q_shwin;

{
=================================================================

PCX LOADING

=================================================================
}

type
  PPByte = ^PByte;
{ Sly- Delphi 6 already has a PIntegerArray type }
{$IFNDEF COMPILER6_UP}
  TIntegerArray = array[0..2222222] of Integer;
  PIntegerArray = ^TIntegerArray;
{$ENDIF}

{
==============
SCR_LoadPCX
==============
}

procedure SCR_LoadPCX(filename: PChar; pic, palette: PPByte; width, height: PInteger);
var
  raw: PByte;
  pcx: pcx_p;
  x, y: Integer;
  len: Integer;
  dataByte, runLength: Integer;
  _out, pix: PByteArray;
begin
  pic := nil;

  //
  // load the file
  //
  len := FS_LoadFile(filename, @raw);

  if (raw = nil) then
    Exit; // Com_Printf ('Bad pcx file %s'#10, filename);

  //
  // parse the PCX file
  //
  pcx := pcx_p(raw); // *** ??? *** need pointer type to structure
  raw := @pcx^.data;

  if (pcx.manufacturer <> #$0A) or
    (pcx.version <> #5) or
    (pcx.encoding <> #1) or
    (pcx.bits_per_pixel <> #8) or
    (pcx.xmax >= 640) or
    (pcx.ymax >= 480) then
  begin
    Com_Printf('Bad pcx file %s'#10, [filename]);
    exit;
  end;

  _out := Z_Malloc((pcx.ymax + 1) * (pcx.xmax + 1));

  pic^ := PByte(_out);

  pix := _out;

  if (palette <> nil) then
  begin
    palette^ := Z_Malloc(768);
    Move(palette^, PChar(Integer(pcx) + len - 768)^, 768);
  end;

  if (width <> nil) then
    width^ := pcx.xmax + 1;
  if (height <> nil) then
    height^ := pcx.ymax + 1;

  y := 0;
  while y <= pcx^.ymax do
  begin
    x := 0;
    while (x <= pcx.xmax) do
    begin
      dataByte := raw^;
      Inc(raw);
      if ((dataByte and $C0) = $C0) then
      begin
        runLength := dataByte and $3F;
        dataByte := raw^;
        Inc(raw);
      end
      else
        runLength := 1;

      while (runLength > 0) do
      begin
        pix[x] := Byte(dataByte);
        Inc(x);
        Dec(runLength);
      end;
      Inc(x);
    end;

    Inc(y);
    Inc(pix, pcx^.xmax + 1);
  end;

  if (Integer(raw) - Integer(pcx) > len) then
  begin
    Com_Printf('PCX file %s was malformed', [filename]);
    Z_Free(pic^);
    pic^ := nil;
  end;

  FS_FreeFile(pcx);
end;

//=============================================================

{
==================
SCR_StopCinematic
==================
}

procedure SCR_StopCinematic;
begin
	cl.cinematictime := 0;	// done
	if (cin.pic <> nil) then
	begin
		Z_Free (cin.pic);
		cin.pic := nil;
	end;
	if (cin.pic_pending <> nil) then
	begin
		Z_Free (cin.pic_pending);
		cin.pic_pending := nil;
	end;
	if (cl.cinematicpalette_active) then
	begin
		re.CinematicSetPalette(nil);
		cl.cinematicpalette_active := false;
	end;
	if (cl.cinematic_file <> 0) then
	begin
		FileClose (cl.cinematic_file);
		cl.cinematic_file := 0;
	end;
	if (cin.hnodes1 <> nil) then
	begin
		Z_Free (cin.hnodes1);
		cin.hnodes1 := nil;
	end;

	// switch back down to 11 khz sound if necessary
	if (cin.restart_sound) then
	begin
		cin.restart_sound := false;
		CL_Snd_Restart_f();
	end;
end;

{
====================
SCR_FinishCinematic

Called when either the cinematic completes, or it is aborted
====================
}

procedure SCR_FinishCinematic;
begin
  // tell the server to advance to the next map / cinematic
  MSG_WriteByte(cls.netchan.message, Integer(clc_stringcmd));
  SZ_Print(cls.netchan.message, va('nextserver %d'#10, [cl.servercount]));
end;

//==========================================================================

{
==================
SmallestNode1
==================
}

function SmallestNode1(numhnodes: integer): integer;
var
  i: integer;
  best, bestnode: integer;
begin
  best := 99999999;
  bestnode := -1;
  for i := 0 to numhnodes - 1 do
  begin
    if (cin.h_used[i] <> 0) then
      continue;
    if (cin.h_count[i] = 0) then
      continue;
    if (cin.h_count[i] < best) then
    begin
      best := cin.h_count[i];
      bestnode := i;
    end;
  end;

  if (bestnode = -1) then
  begin
    result := -1;
    exit;
  end;

  cin.h_used[bestnode] := Integer(true);
  result := bestnode;
end;

{
==================
Huff1TableInit

Reads the 64k counts table and initializes the node trees
==================
}

procedure Huff1TableInit;
var
  prev: integer;
  j: integer;
  node: PIntegerArray;
  nodebase: PInteger;
  counts: array[0..255] of byte;
  numhnodes: integer;
begin

  cin.hnodes1 := Z_Malloc(256 * 256 * 2 * 4);
  FillChar(cin.hnodes1^, 256 * 256 * 2 * 4, #0);

  for prev := 0 to 255 do
  begin
    FillChar(cin.h_count, sizeof(cin.h_count), #0);
    FillChar(cin.h_used, sizeof(cin.h_used), #0);

    // read a row of counts
    FS_Read(@counts, sizeof(counts), cl.cinematic_file);

    for j := 0 to 255 do
      cin.h_count[j] := counts[j];

    // build the nodes
    numhnodes := 256;
    nodebase := Pointer(Cardinal(cin.hnodes1) + ((prev * 256 * 2)*SizeOf(Integer)));

    while (numhnodes <> 511) do
    begin
      node := Pointer(Cardinal(nodebase) + (((numhnodes - 256) * 2)*SizeOf(Integer)));

      // pick two lowest counts
      node[0] := SmallestNode1(numhnodes);
      if (node[0] = -1) then
        break; // no more

      node[1] := SmallestNode1(numhnodes);
      if (node[1] = -1) then
        break;

      cin.h_count[numhnodes] := cin.h_count[node[0]] + cin.h_count[node[1]];
      numhnodes := numhnodes + 1;
    end;

    cin.numhnodes1[prev] := numhnodes - 1;
  end;
end;

{
==================
Huff1Decompress
==================
}

function Huff1Decompress(_in: cblock_t): cblock_t;
var
  input: pbyte;
  out_p: pbyte;
  nodenum: integer;
  count: integer;
  _out: cblock_t;
  inbyte: integer;
  hnodes: PIntegerArray;
  hnodesbase: PInteger;
begin

  // get decompressed count
  count := _in.data[0] + (_in.data[1] shl 8) + (_in.data[2] shl 16) + (_in.data[3] shl 24);
  input := Pointer(Cardinal(_in.data) + 4);
  _out.data := Z_Malloc(count);
  out_p := PByte(_out.data);

  // read bits

  hnodesbase := PInteger(Cardinal(cin.hnodes1) - SizeOf(Integer) * (256 * 2)); // nodes 0-255 aren't stored

  hnodes := PIntegerArray(hnodesbase);
  nodenum := cin.numhnodes1[0];
  while (count <> 0) do
  begin
    inbyte := input^;
    Inc(Input);
    //-----------
    if (nodenum < 256) then
    begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -