📄 cl_cin.pas
字号:
(*
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 + -