First revision of our scripted... thing
This commit is contained in:
parent
50d599ef71
commit
1dacf2c46e
|
@ -0,0 +1,4 @@
|
|||
_bin/*
|
||||
_build/*
|
||||
_deps/*
|
||||
_tmp/*
|
125
README
125
README
|
@ -1,5 +1,122 @@
|
|||
Half-Life: Shareware Data
|
||||
Half-Life: PAK0.PAK generator
|
||||
|
||||
This repository contains scripts to generate a free installation
|
||||
of Half-Life. We stripping the content straight from installers
|
||||
of demos and other official, free downloads.
|
||||
This repository contains scripts to generate a pak0.pak of
|
||||
Half-Life that is identical to the one that ships on all original disc
|
||||
pressings, when it still talked to the World Opponent Network
|
||||
online service.
|
||||
|
||||
The Steam releases got rid of .pak files altogether, because they
|
||||
(at one point) switched to .gcf archives. Since the SteamPipe update,
|
||||
all files are now completely loose and enforcing file consistency is
|
||||
impossible for source ports.
|
||||
|
||||
These scripts within are stripping the content straight from installers
|
||||
of demos and other official, free downloads.
|
||||
|
||||
This will only build you a pak0.pak file that will pass server purity
|
||||
checks so that you can play multiplayer via source ports and things.
|
||||
This will not grant you a complete install of Half-Life. This will
|
||||
not allow you to play Half-LIfe on Steam or by itself.
|
||||
|
||||
We will still have to improvise where other loose files come from.
|
||||
I've found some good substitutes. If you want it to be truly authentic,
|
||||
please find a 1.0.0.5 of Game of the Year disc pressing of Half-Life
|
||||
and rip the data yourself.
|
||||
|
||||
|
||||
Sources:
|
||||
|
||||
Half-Life: Uplink (web installer)
|
||||
Half-Life Patch 1.1.1.0 (English)
|
||||
Half-Life: Opposing Force - Standalone Demo
|
||||
Half-Life SDK v2.3 Setup
|
||||
Steam Installer with Half-Life Cache
|
||||
|
||||
|
||||
Requirements:
|
||||
|
||||
- approximately 4 GB of disk space
|
||||
- working C compiler
|
||||
- GNU make (probably)
|
||||
- wget
|
||||
- magick
|
||||
|
||||
|
||||
Getting started:
|
||||
|
||||
Run `./start.sh` and wait a few minutes. Make yourself some tea/coffee.
|
||||
|
||||
If you want to speed up the process, get these files off your NFS/NAS:
|
||||
|
||||
hl1110.exe
|
||||
hl_sdk_v23.exe
|
||||
hluplink.exe
|
||||
opfordemofull.exe,
|
||||
steaminstall_halflife.exe
|
||||
|
||||
...and place them alongside this README file.
|
||||
|
||||
|
||||
Script explanation:
|
||||
|
||||
./build_tools.sh builds bmpfix, {hl,pak}extract, qfiles, rewise and
|
||||
places them into ./_bin
|
||||
|
||||
./dl_sources.sh (no args) downloads and sha512 checks the install
|
||||
files.
|
||||
|
||||
./rip_sources.sh (no args) extracts the files, and does trickery to
|
||||
make 2 bad-CRC files work
|
||||
|
||||
./build_pak0.sh [gamedir] will read games/[gamedir]-pak0.sha256 and
|
||||
assemble the pak0.pak
|
||||
|
||||
./build_loose.sh [gamedir] will read games[gamedir.sha256 and finds
|
||||
other desired loose files
|
||||
|
||||
./ccase.sh fixes case sensitivity issues
|
||||
|
||||
the end result is placed into ./_build for you to copy wherever.
|
||||
All the directories prefixed with '_' can be removed, as they're
|
||||
created by the scripts.
|
||||
|
||||
|
||||
Thanks:
|
||||
|
||||
Xylemon - for being the top dog that kept motivating me and for
|
||||
delivering pizza onto my desk
|
||||
|
||||
Theuaredead` - for lots of research and pointers on where we can
|
||||
acquire data sets and files
|
||||
|
||||
CYBERDEViL - for blessing us with REWise, a sane wise installer
|
||||
extractor
|
||||
|
||||
HeteroChromia420 - for bothering me for years in regards to the
|
||||
content purity mess
|
||||
|
||||
Valve - I know you don't love HL1 anymore, but thanks for bringing
|
||||
it into this world
|
||||
|
||||
|
||||
License:
|
||||
|
||||
Scripts in the root dir are CC0
|
||||
ccase.sh was distributed by various Linux game ports, unknown author
|
||||
tools/bmpfix is CC0
|
||||
tools/gpl-quake/ contains GNU GPL V2 code.
|
||||
|
||||
|
||||
Dependency licenses:
|
||||
|
||||
hllib is GNU LGPL 2.1
|
||||
hlextract is GNU GPL V2
|
||||
pakextract its own permissive (ISC-styled) license
|
||||
REWise is GNU GPL V3
|
||||
|
||||
|
||||
Need help:
|
||||
|
||||
None of this comes with support, warranty or whatever. Don't bother
|
||||
ANYONE about this. If you want to improve script compatibility or
|
||||
whatever, feel free to reach out.
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#!/bin/sh
|
||||
|
||||
# builds a pak0.pak file for a respective gamedir
|
||||
|
||||
set -e
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo Usage: `basename $0` gamedir >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
FILES_OUTDIR="$(pwd)/_build/halflife/$1"
|
||||
FILES_MISSING="$(pwd)/_build/missing-$1-loose.txt"
|
||||
|
||||
find_file ()
|
||||
{
|
||||
SEARCHNAME=$(basename "${1}")
|
||||
|
||||
#echo "Looking for $SEARCHNAME"
|
||||
|
||||
find "./_tmp" -type f -name "${SEARCHNAME}" | while read FOUND
|
||||
do
|
||||
CHECK=$(sha256sum "${FOUND}" | cut -d ' ' -f 1)
|
||||
#echo "$CHECK == $2"
|
||||
|
||||
if [ "${CHECK}" = "$2" ]
|
||||
then
|
||||
mkdir -p "${FILES_OUTDIR}/$(dirname $1)"
|
||||
cp -v "${FOUND}" "${FILES_OUTDIR}/$1"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -f "${FILES_OUTDIR}/$1" ]
|
||||
then
|
||||
echo "${1}" >> "$FILES_MISSING"
|
||||
fi
|
||||
}
|
||||
|
||||
find_file_whatever ()
|
||||
{
|
||||
echo "Looking for $1"
|
||||
|
||||
find "./_tmp" -type f -path "*/${2}/${1}*" | while read FOUND
|
||||
do
|
||||
mkdir -p "${FILES_OUTDIR}/$(dirname $1)"
|
||||
cp -v "${FOUND}" "${FILES_OUTDIR}/$1"
|
||||
exit 0
|
||||
done
|
||||
}
|
||||
|
||||
if [ ! -d "$FILES_OUTDIR" ]
|
||||
then
|
||||
echo "Please generate a pak0.pak first."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -f "$FILES_MISSING" ]
|
||||
then
|
||||
rm -v "$FILES_MISSING"
|
||||
fi
|
||||
|
||||
while read LINE
|
||||
do
|
||||
FILE=$(echo ${LINE} | cut -d ' ' -f 2)
|
||||
SUM=$(echo ${LINE} | cut -d ' ' -f 1)
|
||||
find_file ${FILE} $SUM $1
|
||||
done < "games/$1.sha256"
|
||||
|
||||
# since we don't need to pass purity checks for these
|
||||
# we'll find the next best equivalent
|
||||
while read LINE
|
||||
do
|
||||
FILE=$(echo ${LINE} | cut -d ' ' -f 2)
|
||||
find_file_whatever ${FILE} $1
|
||||
done < "$FILES_MISSING"
|
|
@ -0,0 +1,89 @@
|
|||
#!/bin/sh
|
||||
|
||||
# builds a pak0.pak file for a respective gamedir
|
||||
|
||||
export PATH=$(pwd)/_bin:$PATH;
|
||||
|
||||
set -e
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo Usage: `basename $0` gamedir >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
PAK0_OUTDIR="$(pwd)/_build/halflife/$1-pak0"
|
||||
FINAL_TEST=$(cat "sums/$1_pak0.sha512" | cut -d ' ' -f 1)
|
||||
|
||||
find_file ()
|
||||
{
|
||||
SEARCHNAME=$(basename "${1}")
|
||||
|
||||
#echo "Looking for $SEARCHNAME"
|
||||
|
||||
find "./_tmp" -type f -name "${SEARCHNAME}" | while read FOUND
|
||||
do
|
||||
CHECK=$(sha256sum "${FOUND}" | cut -d ' ' -f 1)
|
||||
#echo "$CHECK == $2"
|
||||
|
||||
if [ "${CHECK}" = "$2" ]
|
||||
then
|
||||
mkdir -p "${PAK0_OUTDIR}/$(dirname $1)"
|
||||
cp -v "${FOUND}" "${PAK0_OUTDIR}/$1"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ! -f "${PAK0_OUTDIR}/$1" ]
|
||||
then
|
||||
echo "${1}" >> "./_build/missing-$3-pak0.txt"
|
||||
fi
|
||||
}
|
||||
|
||||
# clean up
|
||||
if [ -d "$PAK0_OUTDIR" ]
|
||||
then
|
||||
rm -rf "$PAK0_OUTDIR"
|
||||
fi
|
||||
mkdir -p "$PAK0_OUTDIR"
|
||||
|
||||
if [ -f "./_build/missing-$1-pak0.txt" ]
|
||||
then
|
||||
rm "./_build/missing-$1-pak0.txt"
|
||||
fi
|
||||
|
||||
while read LINE
|
||||
do
|
||||
FILE=$(echo ${LINE} | cut -d ' ' -f 2)
|
||||
SUM=$(echo ${LINE} | cut -d ' ' -f 1)
|
||||
find_file ${FILE} $SUM $1
|
||||
done < "games/$1-pak0.sha256"
|
||||
|
||||
# move the qfiles script over
|
||||
mkdir -p "$PAK0_OUTDIR/src/"
|
||||
cp -v "games/$1.dat" "$PAK0_OUTDIR/src/files.dat"
|
||||
|
||||
cd "$PAK0_OUTDIR/src/"
|
||||
qfiles -pak 0
|
||||
|
||||
FINAL_CHECK=$(sha512sum "$PAK0_OUTDIR/pak0.pak" | cut -d ' ' -f 1)
|
||||
|
||||
echo "Desired SHA512: ${FINAL_TEST}"
|
||||
echo "Generated SHA512: ${FINAL_CHECK}"
|
||||
|
||||
if [ "${FINAL_CHECK}" = "${FINAL_TEST}" ]
|
||||
then
|
||||
echo "$1's pak0.pak has been built and verified!"
|
||||
else
|
||||
echo "$1's pak0.pak FAILED the check. Will not pass purity test."
|
||||
fi
|
||||
|
||||
cd "$PAK0_OUTDIR/../"
|
||||
mkdir -p "./$1"
|
||||
mv "$PAK0_OUTDIR/pak0.pak" "./$1/pak0.pak"
|
||||
rm -rf "$PAK0_OUTDIR"
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
DEPSDIR="$(pwd)/_deps"
|
||||
BINDIR="$(pwd)/_bin"
|
||||
INCTOOLDIR="$(pwd)/tools"
|
||||
|
||||
if [ -d "$DEPSDIR" ]
|
||||
then
|
||||
rm -rf "$DEPSDIR"
|
||||
fi
|
||||
|
||||
if [ -d "$BINDIR" ]
|
||||
then
|
||||
rm -rf "$BINDIR"
|
||||
fi
|
||||
|
||||
mkdir "$DEPSDIR"
|
||||
mkdir "$BINDIR"
|
||||
cd "$DEPSDIR"
|
||||
|
||||
git clone https://notabug.org/CYBERDEViL/REWise
|
||||
cd REWise
|
||||
make
|
||||
mv -v rewise "$BINDIR/rewise"
|
||||
|
||||
cd "$DEPSDIR"
|
||||
git clone https://github.com/RavuAlHemio/hllib
|
||||
cd hllib/HLLib
|
||||
make
|
||||
cd ../HLExtract
|
||||
make
|
||||
mv -v hlextract "$BINDIR/hlextract"
|
||||
|
||||
cd "$DEPSDIR"
|
||||
git clone https://github.com/yquake2/pakextract
|
||||
cd pakextract
|
||||
make
|
||||
mv -v pakextract "$BINDIR/pakextract"
|
||||
|
||||
cd "$INCTOOLDIR/bmpfix"
|
||||
cc -o bmpfix bmpfix.c
|
||||
mv -v bmpfix "$BINDIR/bmpfix"
|
||||
|
||||
cd "$INCTOOLDIR/gpl-quake"
|
||||
cc -o qfiles cmdlib.c qfiles.c
|
||||
mv -v qfiles "$BINDIR/qfiles"
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/sh
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo Usage: `basename $0` [-r ] file... >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "$1" = "-r" ]
|
||||
then
|
||||
recursive=1
|
||||
shift
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
else
|
||||
recursive=0
|
||||
fi
|
||||
|
||||
for i in "$@"
|
||||
do
|
||||
new=`echo $i | tr "[:upper:]" "[:lower:]"`
|
||||
if [ "$new" != "$i" ]
|
||||
then
|
||||
echo $i "->" $new >&2
|
||||
mv "$i" "$new"
|
||||
fi
|
||||
if [ $recursive = 1 -a -d "$new" ]
|
||||
then
|
||||
$0 -r "$new"/*
|
||||
fi
|
||||
done
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
|
||||
# fetches all of our download sources (and verifies them)
|
||||
set -e
|
||||
|
||||
fetch_resource()
|
||||
{
|
||||
BASENAME=$(basename "$1")
|
||||
SHA512FILE=$(cat "./sums/$BASENAME.sha512")
|
||||
|
||||
if [ ! -f "$BASENAME" ]
|
||||
then
|
||||
printf "Grabbing $2..."
|
||||
wget -nc "$1"
|
||||
printf "\n"
|
||||
fi
|
||||
|
||||
SHA512SUM=$(sha512sum "$BASENAME")
|
||||
|
||||
if [ "$SHA512SUM" = "$SHA512FILE" ]
|
||||
then
|
||||
printf "$BASENAME has been verified.\n"
|
||||
else
|
||||
printf "$BASENAME has the invalid sha512sum. Error!\n"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
fetch_resource "http://archive.org/download/Half-lifeUplink/hluplink.exe" "Half-Life: Uplink"
|
||||
fetch_resource "http://archive.org/download/half-life-patches/English/Update 1.1.1.0 English/hl1110.exe" "Half-Life: Patch 1.1.1.0"
|
||||
fetch_resource "https://archive.org/download/opfor-demo/opfordemofull.exe" "Half-Life: Opposing Force - Demo"
|
||||
fetch_resource "https://downloads.ammahls.com/HLSDK/hl_sdk_v23.exe"
|
||||
fetch_resource "http://archive.org/download/steaminstall_halflife/steaminstall_halflife.exe" "Steam Installer with Half-Life Cache"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
d63e152db6d950f671356c4da0d8a1966e0d940a2166b61678e3a6d46644cd7c xeno.wad
|
||||
0f5c3ae49af4e72f4f26752c1fd5dfbea8f88859f1097badf8733fa6093a8f95 liquids.wad
|
||||
d9d16c2c55f02e5767ce6295720cb7032733d3469f2258f665835ff34da3bac4 settings.scr
|
||||
17726e8174729011c7ea4e1e37b4ccfe7a9aa4abb82c2aaca87872cbe0c106d0 decals.wad
|
||||
4f27bc35d508c4b7226ebe6d529b00f2cabd3ee989aafe7ce2f23703e98c214e server.cfg
|
||||
bff7ad40b9b6ff446d56cf3fd05fd2e50c8d8d186dade45549e3313680815e82 spraypaint.wad
|
||||
38ababf773463fdf6133005d13e543098fc42392b458057f239469b764691300 halflife.wad
|
||||
eda968bb31d28c3930509b303c35dd576d7fef98d68c67a3bee9d1846a456b6e woncomm.lst
|
||||
cd36d358e0a0ab5f654816a0e3d606e1267aa6014ff9f11462b3b4ede5f59487 profile.lst
|
||||
8aa1d462cf294875fe87f7a8197d05b385941959a82e1e614cd02429f4ef12cf liblist.gam
|
||||
efce3f5735ffb05ccf493c980bd61b774e43ce37ec12c0402d43400e07a6743e mapcycle.txt
|
||||
6fd53d6ef8d704299734018e3069ec12551e7fb2065804a1d4e5c936ac4033bd gfx.wad
|
||||
4bbc4680030a300fc535279ab08362e5b5ded8189065f852b3b78052ddfd11bf media/launch_dnmenu1.wav
|
||||
4ce170dfa11f980075f8b6a8a85c3cf78eb59f8766a26b721bff0910ad3baf2d media/valve.avi
|
||||
f3429e06124e28f6a69e6ef6bcb89d22103612158de6a0f8348725be1e9ea4b3 media/sierra.avi
|
||||
bb580215824dd89825f114f4fbe5514f0e9783a1ca7bb7aed2376fadc349b6aa media/launch_select2.wav
|
||||
5140ee43c6ba8cfab956c405f22f4ec989f427305d5b921be115b2c789451b3f media/launch_glow1.wav
|
||||
894ef53ebfaad82a3b2c900b4d2eff5ba4e8fdf1ee339cdbb2e82f6e614fb1df media/launch_select1.wav
|
||||
89eea4b29e3c5272a688e1a42db8a17f6b878c805ffea467edb1e5ad03b47f3d media/logo.avi
|
||||
3a8178df0cda00bf44bf7982ac5f260ba4335bc661da83a06ee99faa379f530b media/launch_deny1.wav
|
||||
913ead8450ba2e23c2b10aad5bf29ba923f21fb1ba58943044081a7938ddf915 media/launch_upmenu1.wav
|
||||
98e2d0a6c5a8c0adf9f75bdbe627b433d36d2d9c26a7b7843fe8ea892b6d7356 media/launch_deny2.wav
|
||||
b9ac3a6c455fa54a11d4f00f8248909800b8b19f84e84bb35e826e4c137f262d cached.wad
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
|
||||
# extracts all the sources into ./_tmp that we got
|
||||
# with dl_sources.sh
|
||||
|
||||
export PATH=$(pwd)/_bin:$PATH;
|
||||
|
||||
set -e
|
||||
|
||||
x_rewise()
|
||||
{
|
||||
mkdir "./_tmp/$1"
|
||||
rewise -x "./_tmp/$1" "$1"
|
||||
}
|
||||
|
||||
sz_extract()
|
||||
{
|
||||
7z x "$1"
|
||||
}
|
||||
|
||||
|
||||
# clean up
|
||||
if [ -d "./_tmp" ]
|
||||
then
|
||||
rm -rf "./_tmp"
|
||||
fi
|
||||
mkdir "./_tmp"
|
||||
|
||||
# extract our sources
|
||||
x_rewise "hluplink.exe"
|
||||
x_rewise "hl1110.exe"
|
||||
x_rewise "opfordemofull.exe"
|
||||
x_rewise "hl_sdk_v23.exe"
|
||||
x_rewise "steaminstall_halflife.exe"
|
||||
|
||||
mkdir -p "./_tmp/hluplink-pak0"
|
||||
pakextract -o "./_tmp/hluplink-pak0" "./_tmp/hluplink.exe/MAINDIR/valve/pak0.PAK"
|
||||
|
||||
mkdir -p "./_tmp/opfordemofull-pak0"
|
||||
pakextract -o "./_tmp/opfordemofull-pak0" "./_tmp/opfordemofull.exe/MAINDIR/valve/pak0.PAK"
|
||||
|
||||
mkdir -p "./_tmp/half-life.gcf"
|
||||
hlextract -p "./_tmp/steaminstall_halflife.exe/MAINDIR/SteamApps/half-life.gcf" -d "./_tmp/half-life.gcf" -e "root/valve/"
|
||||
|
||||
./ccase.sh -r "./_tmp"
|
||||
|
||||
# if anything goes wrong here, it's probably imagemagick messing with the image
|
||||
magick "./_tmp/hluplink-pak0/gfx/shell/btns_main.bmp" -compress none -crop 156x4836+0+0 BMP3:"./_tmp/btns_main.bmp"
|
||||
bmpfix "./_tmp/hl1110.exe/maindir/valve/models/player/hgrunt/hgrunt.bmp"
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
./build_tools.sh
|
||||
./dl_sources.sh
|
||||
./rip_sources.sh
|
||||
./build_pak0.sh valve
|
||||
./build_loose.sh valve
|
||||
|
||||
# the edge cases we simply couldn't automatically fetch, due to path/name quirks
|
||||
cp -v "./_tmp/hl1110.exe/maindir/valve/settings.scr" "./_build/halflife/valve/settings.scr"
|
||||
cp -v "./_tmp/hl1110.exe/maindir/valve/woncomm.lst" "./_build/halflife/valve/woncomm.lst"
|
||||
cp -v "./_tmp/opfordemofull.exe/maindir/valve/media/sierra.avi" "./_build/halflife/valve/media/sierra.avi"
|
||||
cp -v "./_tmp/hluplink.exe/maindir/media/intro.avi" "./_build/halflife/valve/media/valve.avi"
|
||||
cp -v "./_tmp/hluplink.exe/maindir/media/uplink.avi" "./_build/halflife/valve/media/logo.avi"
|
|
@ -0,0 +1 @@
|
|||
b6f7e2142a45b6e56acc9a0b3fe478736b04f7a845cee9977e06b591a137a66cadcaa706e2ba47919cd30e733baf8f32e4dcc2cd608c00b4a0da865562cbdbe8 hl1110.exe
|
|
@ -0,0 +1 @@
|
|||
c3857ac8c5ff657e0a0d36661d251e250d9ff9e23c728d5079c194cedb3c92a38ab34577f0cf4c684852e99c51dfec58654ff41e8d1795efba3fa6a5daf7e82f hl_sdk_v23.exe
|
|
@ -0,0 +1 @@
|
|||
2629fd06db71f2ea8bd7937ee271c7dd8804c0b570b6ccd0d82a93edd94a11cd0b9736719a9a9e4c1545bc11abaef52c05155188970b762d0afbe4ff0a8aa753 hluplink.exe
|
|
@ -0,0 +1 @@
|
|||
a0b30a419b23d9a4a9750ee89a4827be60e501b8ab2e74292040f8a6c27ab25e879bc2496cdebb2fb957b2e86dc4d5bfc29b01c94b6005d5940343b3c6607ee7 opfordemofull.exe
|
|
@ -0,0 +1 @@
|
|||
865027728d38d92ae6c6a05f9c72da162372ab91b40911c716dc62d4c024fe46b21192429d3a25ca68a9d32d034575ef1c5f7a534abe7e8977eeff8db9dd7b04 steaminstall_halflife.exe
|
|
@ -0,0 +1 @@
|
|||
d548f6a62174e30b651a63ef5725c9474409ab4b8c4e5246d179b4816acf7e554f92a36b9c46e456633781e94b3c52c8f31c7887d771c11b6c840be35ddd6868 /usr/share/games/halflife/valve/pak0.pak
|
|
@ -0,0 +1,144 @@
|
|||
/* this program is dedicated to all the cyberpunks out there */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* the format is too annoying for me to give a damn */
|
||||
static byte bmp_header[54];
|
||||
static byte bmp_palette[1024];
|
||||
static byte bmp_buffer[32800];
|
||||
|
||||
typedef union {
|
||||
int rgba:32;
|
||||
struct {
|
||||
byte b:8;
|
||||
byte g:8;
|
||||
byte r:8;
|
||||
byte a:8;
|
||||
} u;
|
||||
} pixel_t;
|
||||
|
||||
pixel_t bmp_pal[256] = {
|
||||
0xffffff, 0xdfffbb, 0xcbefa3, 0xb7df8b, 0xa7cf77, 0x97bf63, 0x87b353,
|
||||
0x77a343, 0x679333, 0x5b8327, 0x4f771b, 0x3f6713, 0x33570b, 0x2b4707,
|
||||
0x1f3700, 0x172b00, 0xfff77f, 0xefeb77, 0xe3df6f, 0xd7cf67, 0xc7c35f,
|
||||
0xbbb75b, 0xafab53, 0x9f9f4b, 0x939347, 0x87833f, 0x7b7737, 0x6b6b33,
|
||||
0x5f5f2b, 0x534f23, 0x43431f, 0x373717, 0x2b2b13, 0x27270f, 0x27270f,
|
||||
0x23230f, 0x23230f, 0x1f230f, 0x1b1f0b, 0x1b1f0b, 0x1b1b0b, 0x171b0b,
|
||||
0x171b0b, 0x131707, 0x131707, 0x0f1307, 0x0f1307, 0x0f1307, 0x9baf87,
|
||||
0x8f9f77, 0x83936b, 0x77875f, 0x6f7753, 0x636b47, 0x575f3b, 0x4f5333,
|
||||
0x434b2b, 0x3b4727, 0x334323, 0x2b3f1f, 0x233717, 0x1b3313, 0x132f13,
|
||||
0x0f2b0f, 0xefcfaf, 0xe7c7a7, 0xdfbf9f, 0xdbb79b, 0xd3b393, 0xcfab8b,
|
||||
0xc7a387, 0xbf9b7f, 0xbb977b, 0xbf9373, 0xc38f6b, 0xc78b63, 0xcb875b,
|
||||
0xcf8353, 0xd37f4b, 0xdb7b43, 0xd36f3f, 0xcb673b, 0xc35f37, 0xbb5733,
|
||||
0xb3532f, 0xab4b2b, 0xa3432b, 0x9f3b27, 0x973723, 0x8f2f1f, 0x872b1f,
|
||||
0x7f231b, 0x771f17, 0x6f1b17, 0x671713, 0x631313, 0xb7876f, 0xab7b63,
|
||||
0xa36f57, 0x9b634b, 0x93573f, 0x874f37, 0x7f472f, 0x773b23, 0x6b331f,
|
||||
0x632b17, 0x5b230f, 0x531f0b, 0x471707, 0x3f1300, 0x370f00, 0x2f0b00,
|
||||
0xd3d7bb, 0xc7cbaf, 0xbbbfa3, 0xafb397, 0xa3a78f, 0x979b83, 0x8f8f77,
|
||||
0x83836f, 0x777763, 0x6b6b57, 0x5f5f4f, 0x535343, 0x47473b, 0x3b3b2f,
|
||||
0x333327, 0x27271f, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x70527a,
|
||||
0x6a4d73, 0x62486b, 0x5c4263, 0x503a57, 0x49354f, 0x423047, 0x3b2a40,
|
||||
0x332538, 0x2a1e2e, 0x231926, 0x1a121c, 0x150f17, 0x0b080c, 0x070507,
|
||||
0x000000, 0x70527a, 0x6a4d73, 0x62486b, 0x5b4263, 0x4f3a57, 0x4a354f,
|
||||
0x423047, 0x3a2a40, 0x342538, 0x2a1e2e, 0x231926, 0x1b071f, 0x130717,
|
||||
0x0b000f, 0x070007, 0x000000, 0x52737a, 0x4d6773, 0x48646b, 0x415a61,
|
||||
0x3c5359, 0x354a4f, 0x2e4045, 0x29393d, 0x223033, 0x1e2b2e, 0x182123,
|
||||
0x141c1e, 0x0f1517, 0x0a0e0f, 0x050707, 0x000000, 0x52727a, 0x4d6a73,
|
||||
0x48636b, 0x425d63, 0x3a5257, 0x354a4f, 0x304247, 0x2a3c40, 0x253438,
|
||||
0x1e2b2e, 0x192326, 0x141d1e, 0x0f1517, 0x0a0e0f, 0x050707, 0x000000,
|
||||
0xffffff, 0xf7f7f7, 0xefefef, 0xe7e7e7, 0xdfdfdf, 0xd7d7d7, 0xcfcfcf,
|
||||
0xc7c7c7, 0xbfbfbf, 0xb7b7b7, 0xafafaf, 0xa7a7a7, 0x9f9f9f, 0x979797,
|
||||
0x8f8f8f, 0x878787, 0x7f7f7f, 0x777777, 0x6f6f6f, 0x676767, 0x5f5f5f,
|
||||
0x575757, 0x4f4f4f, 0x474747, 0x3f3f3f, 0x373737, 0x2f2f2f, 0x272727,
|
||||
0x1f1f1f, 0x171717, 0x0f0f0f, 0x040404
|
||||
};
|
||||
|
||||
byte
|
||||
find_in_pal(byte r, byte g, byte b)
|
||||
{
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (bmp_pal[i].u.r == r && bmp_pal[i].u.g == g && bmp_pal[i].u.b == b)
|
||||
return (byte)i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
process_bmp(char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
struct stat bmp_st;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* There are no other types of palette lumps. Sorry */
|
||||
stat(filename, &bmp_st);
|
||||
if (bmp_st.st_size != 33878) {
|
||||
fprintf(stderr, "%s has invalid player bitmap size, skipping\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* lazily read the clown format in */
|
||||
fread(bmp_header, 1, 54, fp);
|
||||
fread(bmp_palette, 1, 1024, fp);
|
||||
fread(bmp_buffer, 1, 32800, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* convert from 8-bit to 24-bit */
|
||||
for (int i = 0; i < 32800; i += 1) {
|
||||
int palId = bmp_buffer[i] * 4;
|
||||
/* get 24-bit values */
|
||||
byte r = bmp_palette[palId + 2];
|
||||
byte g = bmp_palette[palId + 1];
|
||||
byte b = bmp_palette[palId + 0];
|
||||
|
||||
/* assign the index from the good palette */
|
||||
bmp_buffer[i] = find_in_pal(r, g, b);
|
||||
}
|
||||
|
||||
/* shove the old palette into the new place */
|
||||
for (int i = 0; i < 256; i += 1) {
|
||||
int id = i * 4;
|
||||
bmp_palette[id+2] = bmp_pal[i].u.r;
|
||||
bmp_palette[id+1] = bmp_pal[i].u.g;
|
||||
bmp_palette[id+0] = bmp_pal[i].u.b;
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename, "wb")) == NULL) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fwrite(bmp_header, 1, 54, fp);
|
||||
fwrite(bmp_palette, 1, 1024, fp);
|
||||
fwrite(bmp_buffer, 1, 32800, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
short p;
|
||||
FILE *fPAL;
|
||||
|
||||
if (argc <= 1) {
|
||||
fprintf(stderr, "usage: bmpfix [file ...]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; c++)
|
||||
process_bmp(argv[c]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,867 @@
|
|||
// cmdlib.c
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#ifdef NeXT
|
||||
#include <libc.h>
|
||||
#endif
|
||||
|
||||
#define PATHSEPERATOR '/'
|
||||
|
||||
// set these before calling CheckParm
|
||||
int myargc;
|
||||
char **myargv;
|
||||
|
||||
char com_token[1024];
|
||||
qboolean com_eof;
|
||||
|
||||
qboolean archive;
|
||||
char archivedir[1024];
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Error
|
||||
|
||||
For abnormal program terminations
|
||||
=================
|
||||
*/
|
||||
void Error (char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
printf ("************ ERROR ************\n");
|
||||
|
||||
va_start (argptr,error);
|
||||
vprintf (error,argptr);
|
||||
va_end (argptr);
|
||||
printf ("\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
qdir will hold the path up to the quake directory, including the slash
|
||||
|
||||
f:\quake\
|
||||
/raid/quake/
|
||||
|
||||
gamedir will hold qdir + the game directory (id1, id2, etc)
|
||||
|
||||
*/
|
||||
|
||||
char qdir[1024];
|
||||
char gamedir[1024];
|
||||
|
||||
void SetQdirFromPath (char *path)
|
||||
{
|
||||
char temp[1024];
|
||||
char *c;
|
||||
|
||||
if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
|
||||
{ // path is partial
|
||||
Q_getwd (temp);
|
||||
strcat (temp, path);
|
||||
path = temp;
|
||||
}
|
||||
|
||||
// search for "quake" in path
|
||||
|
||||
for (c=path ; *c ; c++)
|
||||
if (!Q_strncasecmp (c, "halflife", 8))
|
||||
{
|
||||
strncpy (qdir, path, c+9-path);
|
||||
printf ("qdir: %s\n", qdir);
|
||||
c += 9;
|
||||
while (*c)
|
||||
{
|
||||
if (*c == '/' || *c == '\\')
|
||||
{
|
||||
strncpy (gamedir, path, c+1-path);
|
||||
printf ("gamedir: %s\n", gamedir);
|
||||
return;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
Error ("No gamedir in %s", path);
|
||||
return;
|
||||
}
|
||||
Error ("SeetQdirFromPath: no 'halflife' in %s", path);
|
||||
}
|
||||
|
||||
char *ExpandPath (char *path)
|
||||
{
|
||||
static char full[1024];
|
||||
if (!qdir)
|
||||
Error ("ExpandPath called without qdir set");
|
||||
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
|
||||
return path;
|
||||
sprintf (full, "%s%s", qdir, path);
|
||||
return full;
|
||||
}
|
||||
|
||||
char *ExpandPathAndArchive (char *path)
|
||||
{
|
||||
char *expanded;
|
||||
char archivename[1024];
|
||||
|
||||
expanded = ExpandPath (path);
|
||||
|
||||
if (archive)
|
||||
{
|
||||
sprintf (archivename, "%s/%s", archivedir, path);
|
||||
CopyFile (expanded, archivename);
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
|
||||
char *copystring(char *s)
|
||||
{
|
||||
char *b;
|
||||
b = malloc(strlen(s)+1);
|
||||
strcpy (b, s);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
I_FloatTime
|
||||
================
|
||||
*/
|
||||
double I_FloatTime (void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
time (&t);
|
||||
|
||||
return t;
|
||||
#if 0
|
||||
// more precise, less portable
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
static int secbase;
|
||||
|
||||
gettimeofday(&tp, &tzp);
|
||||
|
||||
if (!secbase)
|
||||
{
|
||||
secbase = tp.tv_sec;
|
||||
return tp.tv_usec/1000000.0;
|
||||
}
|
||||
|
||||
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Q_getwd (char *out)
|
||||
{
|
||||
#ifdef WIN32
|
||||
_getcwd (out, 256);
|
||||
strcat (out, "\\");
|
||||
#else
|
||||
getwd (out);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Q_mkdir (char *path)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (_mkdir (path) != -1)
|
||||
return;
|
||||
#else
|
||||
if (mkdir (path, 0777) != -1)
|
||||
return;
|
||||
#endif
|
||||
if (errno != EEXIST)
|
||||
Error ("mkdir %s: %s",path, strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
FileTime
|
||||
|
||||
returns -1 if not present
|
||||
============
|
||||
*/
|
||||
int FileTime (char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (stat (path,&buf) == -1)
|
||||
return -1;
|
||||
|
||||
return buf.st_mtime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_Parse
|
||||
|
||||
Parse a token out of a string
|
||||
==============
|
||||
*/
|
||||
char *COM_Parse (char *data)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
{
|
||||
if (c == 0)
|
||||
{
|
||||
com_eof = true;
|
||||
return NULL; // end of file;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if (c=='/' && data[1] == '/')
|
||||
{
|
||||
while (*data && *data != '\n')
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
|
||||
// handle quoted strings specially
|
||||
if (c == '\"')
|
||||
{
|
||||
data++;
|
||||
do
|
||||
{
|
||||
c = *data++;
|
||||
if (c=='\"')
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
{
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
com_token[len] = c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
||||
break;
|
||||
} while (c>32);
|
||||
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
int Q_strncasecmp (char *s1, char *s2, int n)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if (!n--)
|
||||
return 0; // strings are equal until end point
|
||||
|
||||
if (c1 != c2)
|
||||
{
|
||||
if (c1 >= 'a' && c1 <= 'z')
|
||||
c1 -= ('a' - 'A');
|
||||
if (c2 >= 'a' && c2 <= 'z')
|
||||
c2 -= ('a' - 'A');
|
||||
if (c1 != c2)
|
||||
return -1; // strings not equal
|
||||
}
|
||||
if (!c1)
|
||||
return 0; // strings are equal
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Q_strcasecmp (char *s1, char *s2)
|
||||
{
|
||||
return Q_strncasecmp (s1, s2, 99999);
|
||||
}
|
||||
|
||||
|
||||
char *strupr (char *start)
|
||||
{
|
||||
char *in;
|
||||
in = start;
|
||||
while (*in)
|
||||
{
|
||||
*in = toupper(*in);
|
||||
in++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
char *strlower (char *start)
|
||||
{
|
||||
char *in;
|
||||
in = start;
|
||||
while (*in)
|
||||
{
|
||||
*in = tolower(*in);
|
||||
in++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
MISC FUNCTIONS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CheckParm
|
||||
|
||||
Checks for the given parameter in the program's command line arguments
|
||||
Returns the argument number (1 to argc-1) or 0 if not present
|
||||
=================
|
||||
*/
|
||||
int CheckParm (char *check)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1;i<myargc;i++)
|
||||
{
|
||||
if ( !Q_strcasecmp(check, myargv[i]) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
filelength
|
||||
================
|
||||
*/
|
||||
int filelength (FILE *f)
|
||||
{
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = ftell (f);
|
||||
fseek (f, 0, SEEK_END);
|
||||
end = ftell (f);
|
||||
fseek (f, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
FILE *SafeOpenWrite (char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, "wb");
|
||||
|
||||
if (!f)
|
||||
Error ("Error opening %s: %s",filename,strerror(errno));
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
FILE *SafeOpenRead (char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
|
||||
if (!f)
|
||||
Error ("Error opening %s: %s",filename,strerror(errno));
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void SafeRead (FILE *f, void *buffer, int count)
|
||||
{
|
||||
if ( fread (buffer, 1, count, f) != (size_t)count)
|
||||
Error ("File read failure");
|
||||
}
|
||||
|
||||
|
||||
void SafeWrite (FILE *f, void *buffer, int count)
|
||||
{
|
||||
if (fwrite (buffer, 1, count, f) != (size_t)count)
|
||||
Error ("File read failure");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
LoadFile
|
||||
==============
|
||||
*/
|
||||
int LoadFile (char *filename, void **bufferptr)
|
||||
{
|
||||
FILE *f;
|
||||
int length;
|
||||
void *buffer;
|
||||
|
||||
f = SafeOpenRead (filename);
|
||||
length = filelength (f);
|
||||
buffer = malloc (length+1);
|
||||
((char *)buffer)[length] = 0;
|
||||
SafeRead (f, buffer, length);
|
||||
fclose (f);
|
||||
|
||||
*bufferptr = buffer;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
SaveFile
|
||||
==============
|
||||
*/
|
||||
void SaveFile (char *filename, void *buffer, int count)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = SafeOpenWrite (filename);
|
||||
SafeWrite (f, buffer, count);
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DefaultExtension (char *path, char *extension)
|
||||
{
|
||||
char *src;
|
||||
//
|
||||
// if path doesn't have a .EXT, append extension
|
||||
// (extension should include the .)
|
||||
//
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
while (*src != PATHSEPERATOR && src != path)
|
||||
{
|
||||
if (*src == '.')
|
||||
return; // it has an extension
|
||||
src--;
|
||||
}
|
||||
|
||||
strcat (path, extension);
|
||||
}
|
||||
|
||||
|
||||
void DefaultPath (char *path, char *basepath)
|
||||
{
|
||||
char temp[128];
|
||||
|
||||
if (path[0] == PATHSEPERATOR)
|
||||
return; // absolute path location
|
||||
strcpy (temp,path);
|
||||
strcpy (path,basepath);
|
||||
strcat (path,temp);
|
||||
}
|
||||
|
||||
|
||||
void StripFilename (char *path)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = strlen(path)-1;
|
||||
while (length > 0 && path[length] != PATHSEPERATOR)
|
||||
length--;
|
||||
path[length] = 0;
|
||||
}
|
||||
|
||||
void StripExtension (char *path)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = strlen(path)-1;
|
||||
while (length > 0 && path[length] != '.')
|
||||
{
|
||||
length--;
|
||||
if (path[length] == '/')
|
||||
return; // no extension
|
||||
}
|
||||
if (length)
|
||||
path[length] = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
Extract file parts
|
||||
====================
|
||||
*/
|
||||
void ExtractFilePath (char *path, char *dest)
|
||||
{
|
||||
char *src;
|
||||
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
//
|
||||
// back up until a \ or the start
|
||||
//
|
||||
while (src != path && *(src-1) != PATHSEPERATOR)
|
||||
src--;
|
||||
|
||||
memcpy (dest, path, src-path);
|
||||
dest[src-path] = 0;
|
||||
}
|
||||
|
||||
void ExtractFileBase (char *path, char *dest)
|
||||
{
|
||||
char *src;
|
||||
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
//
|
||||
// back up until a \ or the start
|
||||
//
|
||||
while (src != path && *(src-1) != PATHSEPERATOR)
|
||||
src--;
|
||||
|
||||
while (*src && *src != '.')
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
void ExtractFileExtension (char *path, char *dest)
|
||||
{
|
||||
char *src;
|
||||
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
//
|
||||
// back up until a . or the start
|
||||
//
|
||||
while (src != path && *(src-1) != '.')
|
||||
src--;
|
||||
if (src == path)
|
||||
{
|
||||
*dest = 0; // no extension
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy (dest,src);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
ParseNum / ParseHex
|
||||
==============
|
||||
*/
|
||||
int ParseHex (char *hex)
|
||||
{
|
||||
char *str;
|
||||
int num;
|
||||
|
||||
num = 0;
|
||||
str = hex;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
num <<= 4;
|
||||
if (*str >= '0' && *str <= '9')
|
||||
num += *str-'0';
|
||||
else if (*str >= 'a' && *str <= 'f')
|
||||
num += 10 + *str-'a';
|
||||
else if (*str >= 'A' && *str <= 'F')
|
||||
num += 10 + *str-'A';
|
||||
else
|
||||
Error ("Bad hex number: %s",hex);
|
||||
str++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int ParseNum (char *str)
|
||||
{
|
||||
if (str[0] == '$')
|
||||
return ParseHex (str+1);
|
||||
if (str[0] == '0' && str[1] == 'x')
|
||||
return ParseHex (str+2);
|
||||
return atol (str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
BYTE ORDER FUNCTIONS
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#ifdef _SGI_SOURCE
|
||||
#define __BIG_ENDIAN__
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
short LittleShort (short l)
|
||||
{
|
||||
byte b1,b2;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
|
||||
return (b1<<8) + b2;
|
||||
}
|
||||
|
||||
short BigShort (short l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int LittleLong (int l)
|
||||
{
|
||||
byte b1,b2,b3,b4;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
b3 = (l>>16)&255;
|
||||
b4 = (l>>24)&255;
|
||||
|
||||
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||||
}
|
||||
|
||||
int BigLong (int l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
float LittleFloat (float l)
|
||||
{
|
||||
union {byte b[4]; float f;} in, out;
|
||||
|
||||
in.f = l;
|
||||
out.b[0] = in.b[3];
|
||||
out.b[1] = in.b[2];
|
||||
out.b[2] = in.b[1];
|
||||
out.b[3] = in.b[0];
|
||||
|
||||
return out.f;
|
||||
}
|
||||
|
||||
float BigFloat (float l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
short BigShort (short l)
|
||||
{
|
||||
byte b1,b2;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
|
||||
return (b1<<8) + b2;
|
||||
}
|
||||
|
||||
short LittleShort (short l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int BigLong (int l)
|
||||
{
|
||||
byte b1,b2,b3,b4;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
b3 = (l>>16)&255;
|
||||
b4 = (l>>24)&255;
|
||||
|
||||
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||||
}
|
||||
|
||||
int LittleLong (int l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
float BigFloat (float l)
|
||||
{
|
||||
union {byte b[4]; float f;} in, out;
|
||||
|
||||
in.f = l;
|
||||
out.b[0] = in.b[3];
|
||||
out.b[1] = in.b[2];
|
||||
out.b[2] = in.b[1];
|
||||
out.b[3] = in.b[0];
|
||||
|
||||
return out.f;
|
||||
}
|
||||
|
||||
float LittleFloat (float l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//=======================================================
|
||||
|
||||
|
||||
// FIXME: byte swap?
|
||||
|
||||
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
|
||||
// and the initial and final xor values shown below... in other words, the
|
||||
// CCITT standard CRC used by XMODEM
|
||||
|
||||
#define CRC_INIT_VALUE 0xffff
|
||||
#define CRC_XOR_VALUE 0x0000
|
||||
|
||||
static unsigned short crctable[256] =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
void CRC_Init(unsigned short *crcvalue)
|
||||
{
|
||||
*crcvalue = CRC_INIT_VALUE;
|
||||
}
|
||||
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
|
||||
{
|
||||
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
|
||||
}
|
||||
|
||||
unsigned short CRC_Value(unsigned short crcvalue)
|
||||
{
|
||||
return crcvalue ^ CRC_XOR_VALUE;
|
||||
}
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
============
|
||||
CreatePath
|
||||
============
|
||||
*/
|
||||
void CreatePath (char *path)
|
||||
{
|
||||
char *ofs, c;
|
||||
|
||||
for (ofs = path+1 ; *ofs ; ofs++)
|
||||
{
|
||||
c = *ofs;
|
||||
if (c == '/' || c == '\\')
|
||||
{ // create the directory
|
||||
*ofs = 0;
|
||||
Q_mkdir (path);
|
||||
*ofs = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
CopyFile
|
||||
|
||||
Used to archive source files
|
||||
============
|
||||
*/
|
||||
void CopyFile (char *from, char *to)
|
||||
{
|
||||
void *buffer;
|
||||
int length;
|
||||
|
||||
length = LoadFile (from, &buffer);
|
||||
CreatePath (to);
|
||||
SaveFile (to, buffer, length);
|
||||
free (buffer);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
// cmdlib.h
|
||||
|
||||
#ifndef __CMDLIB__
|
||||
#define __CMDLIB__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef __BYTEBOOL__
|
||||
#define __BYTEBOOL__
|
||||
typedef enum {false, true} qboolean;
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
// the dec offsetof macro doesn't work very well...
|
||||
#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
|
||||
|
||||
|
||||
// set these before calling CheckParm
|
||||
extern int myargc;
|
||||
extern char **myargv;
|
||||
|
||||
char *strupr (char *in);
|
||||
char *strlower (char *in);
|
||||
int Q_strncasecmp (char *s1, char *s2, int n);
|
||||
int Q_strcasecmp (char *s1, char *s2);
|
||||
void Q_getwd (char *out);
|
||||
|
||||
int filelength (FILE *f);
|
||||
int FileTime (char *path);
|
||||
|
||||
void Q_mkdir (char *path);
|
||||
|
||||
extern char qdir[1024];
|
||||
extern char gamedir[1024];
|
||||
void SetQdirFromPath (char *path);
|
||||
char *ExpandPath (char *path);
|
||||
char *ExpandPathAndArchive (char *path);
|
||||
|
||||
|
||||
double I_FloatTime (void);
|
||||
|
||||
void Error (char *error, ...);
|
||||
int CheckParm (char *check);
|
||||
|
||||
FILE *SafeOpenWrite (char *filename);
|
||||
FILE *SafeOpenRead (char *filename);
|
||||
void SafeRead (FILE *f, void *buffer, int count);
|
||||
void SafeWrite (FILE *f, void *buffer, int count);
|
||||
|
||||
int LoadFile (char *filename, void **bufferptr);
|
||||
void SaveFile (char *filename, void *buffer, int count);
|
||||
|
||||
void DefaultExtension (char *path, char *extension);
|
||||
void DefaultPath (char *path, char *basepath);
|
||||
void StripFilename (char *path);
|
||||
void StripExtension (char *path);
|
||||
|
||||
void ExtractFilePath (char *path, char *dest);
|
||||
void ExtractFileBase (char *path, char *dest);
|
||||
void ExtractFileExtension (char *path, char *dest);
|
||||
|
||||
int ParseNum (char *str);
|
||||
|
||||
short BigShort (short l);
|
||||
short LittleShort (short l);
|
||||
int BigLong (int l);
|
||||
int LittleLong (int l);
|
||||
float BigFloat (float l);
|
||||
float LittleFloat (float l);
|
||||
|
||||
|
||||
char *COM_Parse (char *data);
|
||||
|
||||
extern char com_token[1024];
|
||||
extern qboolean com_eof;
|
||||
|
||||
char *copystring(char *s);
|
||||
|
||||
|
||||
void CRC_Init(unsigned short *crcvalue);
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
|
||||
unsigned short CRC_Value(unsigned short crcvalue);
|
||||
|
||||
void CreatePath (char *path);
|
||||
void CopyFile (char *from, char *to);
|
||||
|
||||
extern qboolean archive;
|
||||
extern char archivedir[1024];
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,179 @@
|
|||
|
||||
#include "cmdlib.h"
|
||||
|
||||
#define MAX_FILES 4096
|
||||
|
||||
#define MAX_DATA_PATH 512
|
||||
|
||||
char precache_files[MAX_FILES][MAX_DATA_PATH];
|
||||
int precache_files_block[MAX_FILES];
|
||||
int numfiles;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[56];
|
||||
int filepos, filelen;
|
||||
} packfile_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char id[4];
|
||||
int dirofs;
|
||||
int dirlen;
|
||||
} packheader_t;
|
||||
|
||||
packfile_t pfiles[4096], *pf;
|
||||
FILE *packhandle;
|
||||
int packbytes;
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
PackFile
|
||||
|
||||
Copy a file into the pak file
|
||||
===========
|
||||
*/
|
||||
void PackFile (char *src, char *name)
|
||||
{
|
||||
FILE *in;
|
||||
int remaining, count;
|
||||
char buf[4096];
|
||||
|
||||
if ( (byte *)pf - (byte *)pfiles > sizeof(pfiles) )
|
||||
Error ("Too many files in pak file");
|
||||
|
||||
in = SafeOpenRead (src);
|
||||
remaining = filelength (in);
|
||||
|
||||
pf->filepos = LittleLong (ftell (packhandle));
|
||||
pf->filelen = LittleLong (remaining);
|
||||
strcpy (pf->name, name);
|
||||
printf ("%64s : %7i\n", pf->name, remaining);
|
||||
|
||||
packbytes += remaining;
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
if (remaining < sizeof(buf))
|
||||
count = remaining;
|
||||
else
|
||||
count = sizeof(buf);
|
||||
SafeRead (in, buf, count);
|
||||
SafeWrite (packhandle, buf, count);
|
||||
remaining -= count;
|
||||
}
|
||||
|
||||
fclose (in);
|
||||
pf++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
CopyQFiles
|
||||
===========
|
||||
*/
|
||||
void CopyQFiles (int blocknum)
|
||||
{
|
||||
int i, p;
|
||||
char srcfile[1024];
|
||||
char destfile[1024];
|
||||
char name[1024];
|
||||
packheader_t header;
|
||||
int dirlen;
|
||||
unsigned short crc;
|
||||
|
||||
// create a pak file
|
||||
pf = pfiles;
|
||||
|
||||
sprintf (destfile, "%spak%i.pak", gamedir, blocknum);
|
||||
packhandle = SafeOpenWrite (destfile);
|
||||
SafeWrite (packhandle, &header, sizeof(header));
|
||||
|
||||
blocknum++;
|
||||
|
||||
for (i=0 ; i<numfiles ; i++)
|
||||
{
|
||||
if (precache_files_block[i] != blocknum)
|
||||
continue;
|
||||
sprintf (srcfile,"%s%s",gamedir, precache_files[i]);
|
||||
PackFile (srcfile, precache_files[i]);
|
||||
}
|
||||
|
||||
header.id[0] = 'P';
|
||||
header.id[1] = 'A';
|
||||
header.id[2] = 'C';
|
||||
header.id[3] = 'K';
|
||||
dirlen = (byte *)pf - (byte *)pfiles;
|
||||
header.dirofs = LittleLong(ftell (packhandle));
|
||||
header.dirlen = LittleLong(dirlen);
|
||||
|
||||
SafeWrite (packhandle, pfiles, dirlen);
|
||||
|
||||
fseek (packhandle, 0, SEEK_SET);
|
||||
SafeWrite (packhandle, &header, sizeof(header));
|
||||
fclose (packhandle);
|
||||
|
||||
// do a crc of the file
|
||||
CRC_Init (&crc);
|
||||
for (i=0 ; i<dirlen ; i++)
|
||||
CRC_ProcessByte (&crc, ((byte *)pfiles)[i]);
|
||||
|
||||
i = pf - pfiles;
|
||||
printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
ReadFiles
|
||||
=============
|
||||
*/
|
||||
int ReadFiles (void)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
f = SafeOpenRead ("files.dat");
|
||||
|
||||
fscanf(f, "%i\n", &numfiles);
|
||||
|
||||
for (i = 0; i < numfiles ; i++) {
|
||||
fscanf (f, "%i %s\n", &precache_files_block[i], precache_files[i]);
|
||||
printf("%s\n", precache_files[i]);
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
printf ("%i files\n", numfiles);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
main
|
||||
=============
|
||||
*/
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
printf ("qfiles -pak <0 / 1> : build a .pak file\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
SetQdirFromPath ("");
|
||||
|
||||
ReadFiles ();
|
||||
|
||||
if (!strcmp (argv[1], "-pak"))
|
||||
{
|
||||
CopyQFiles (atoi(argv[2]));
|
||||
}
|
||||
else
|
||||
Error ("unknown command: %s", argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue