egs_files: Move the nbl packing functions to egs_files.

This commit is contained in:
Loïc Hoguin 2010-11-06 01:27:16 +01:00
parent dc2968cbce
commit 35bcf4595e
3 changed files with 67 additions and 88 deletions

View File

@ -1,86 +0,0 @@
%% @author Loïc Hoguin <essen@dev-extend.eu>
%% @copyright 2010 Loïc Hoguin.
%% @doc Library for packing and unpacking NBL files.
%%
%% This file is part of EGS.
%%
%% EGS is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Affero General Public License as
%% published by the Free Software Foundation, either version 3 of the
%% License, or (at your option) any later version.
%%
%% EGS is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU Affero General Public License for more details.
%%
%% You should have received a copy of the GNU Affero General Public License
%% along with EGS. If not, see <http://www.gnu.org/licenses/>.
-module(nbl).
-export([pack/1]).
%% @doc Pack an nbl file according to the given Options.
%% Example usage: nbl:pack([{files, [{file, "table.rel", [16#184, 16#188, 16#1a0]}, {file, "text.bin", []}]}]).
pack(Options) ->
Files = proplists:get_value(files, Options),
{Header, Data, DataSize, PtrArray, PtrArraySize} = pack_files(Files),
NbFiles = length(Files),
HeaderSize = 16#30 + 16#60 * NbFiles,
CompressedDataSize = 0,
EncryptSeed = 0,
<< $N, $M, $L, $L, 2:16/little, 16#1300:16, HeaderSize:32/little, NbFiles:32/little,
DataSize:32/little, CompressedDataSize:32/little, PtrArraySize:32/little, EncryptSeed:32/little,
0:128, Header/binary, Data/binary, PtrArray/binary >>.
%% @doc Pack a list of files and return the header, data and pointer array parts.
pack_files(Files) ->
pack_files(Files, {[], [], [], 0, 0}).
pack_files([], {AccH, AccD, AccP, _FilePos, _PtrIndex}) ->
BinH = iolist_to_binary(lists:reverse(AccH)),
PaddingH = 8 * (16#7d0 - (byte_size(BinH) rem 16#800)),
PaddingH2 = if PaddingH =< 0 -> 16#800 + PaddingH; true -> PaddingH end,
BinD = iolist_to_binary(lists:reverse(AccD)),
PaddingD = 8 * (16#800 - (byte_size(BinD) rem 16#800)),
BinP = iolist_to_binary(lists:reverse(AccP)),
PtrSize = byte_size(BinP),
PtrArray = case PtrSize of
0 -> << >>;
_ ->
PaddingP = 8 * (16#800 - (byte_size(BinP) rem 16#800)),
<< BinP/binary, 0:PaddingP >>
end,
{<< BinH/binary, 0:PaddingH2 >>,
<< BinD/binary, 0:PaddingD >>, byte_size(BinD),
PtrArray, PtrSize};
pack_files([{data, Filename, Data, PtrList}|Tail], {AccH, AccD, AccP, FilePos, PtrIndex}) ->
ID = case filename:extension(Filename) of
".bin" -> << $S, $T, $D, 0 >>;
[$.|String] -> list_to_binary(string:to_upper(String ++ [0]))
end,
FilenamePaddingBits = 8 * (32 - length(Filename)),
DataSize = byte_size(Data),
DataPadding = 16#20 - (DataSize rem 16#20),
DataPaddingBits = 8 * DataPadding,
DataSizeWithPadding = DataSize + DataPadding,
PtrSize = 4 * length(PtrList),
BinH = << ID/binary, 16#60000000:32, 0:64, (list_to_binary(Filename))/binary, 0:FilenamePaddingBits,
FilePos:32/little, DataSize:32/little, PtrIndex:32/little, PtrSize:32/little >>,
NXIF = case filename:extension(Filename) of
".bin" -> << 0:256 >>;
_ -> pack_nxif(DataSize, PtrSize)
end,
BinH2 = << BinH/binary, NXIF/binary >>,
BinD = << Data/binary, 0:DataPaddingBits >>,
BinP = iolist_to_binary([ << Ptr:32/little >> || Ptr <- PtrList]),
pack_files(Tail, {[BinH2|AccH], [BinD|AccD], [BinP|AccP], FilePos + DataSizeWithPadding, PtrIndex + PtrSize});
pack_files([{file, Filename, PtrList}|Tail], Acc) ->
{ok, Data} = file:read_file(Filename),
pack_files([{data, Filename, Data, PtrList}|Tail], Acc).
%% @doc Return an NXIF chunk data for a specific data and pointer array size.
pack_nxif(DataSize, PtrSize) ->
DataSize2 = DataSize + 16#20,
PtrSize2 = PtrSize + 16#20 - (PtrSize rem 16#20),
<< $N, $X, $I, $F, 16#18000000:32, 16#01000000:32, 16#20000000:32,
DataSize:32/little, DataSize2:32/little, PtrSize2:32/little, 16#01000000:32 >>.

View File

@ -93,7 +93,7 @@ get_counter(CounterID, Cache) ->
ConfFilename = Dir ++ "counter.conf",
{TableRelData, TableRelPtrs} = egs_files:load_table_rel(ConfFilename),
TextBinData = egs_files:load_text_bin(Dir ++ "text.bin.en_US.txt"),
CounterNbl = nbl:pack([{files, [
CounterNbl = egs_files:nbl_pack([{files, [
{data, "table.rel", TableRelData, TableRelPtrs},
{data, "text.bin", TextBinData, []}
]}]),

View File

@ -18,7 +18,7 @@
%% along with EGS. If not, see <http://www.gnu.org/licenses/>.
-module(egs_files).
-export([load_counter_pack/2, load_table_rel/1, load_text_bin/1]).
-export([load_counter_pack/2, load_table_rel/1, load_text_bin/1, nbl_pack/1]).
%% @doc Build a counter's pack file, options and return them along with the background value.
load_counter_pack(ConfFilename, CounterNbl) ->
@ -128,3 +128,68 @@ load_text_bin_strings([String|Tail], Pos, PosList, Acc) ->
String2 = re:replace(String, "~.n.", "\n\0", [global, {return, binary}]),
String3 = << String2/binary, 0, 0 >>,
load_text_bin_strings(Tail, Pos + byte_size(String3), [Pos|PosList], [String3|Acc]).
%% @doc Pack an nbl file according to the given Options.
%% Example usage: nbl:pack([{files, [{file, "table.rel", [16#184, 16#188, 16#1a0]}, {file, "text.bin", []}]}]).
nbl_pack(Options) ->
Files = proplists:get_value(files, Options),
{Header, Data, DataSize, PtrArray, PtrArraySize} = nbl_pack_files(Files),
NbFiles = length(Files),
HeaderSize = 16#30 + 16#60 * NbFiles,
CompressedDataSize = 0,
EncryptSeed = 0,
<< $N, $M, $L, $L, 2:16/little, 16#1300:16, HeaderSize:32/little, NbFiles:32/little,
DataSize:32/little, CompressedDataSize:32/little, PtrArraySize:32/little, EncryptSeed:32/little,
0:128, Header/binary, Data/binary, PtrArray/binary >>.
%% @doc Pack a list of files and return the header, data and pointer array parts.
nbl_pack_files(Files) ->
nbl_pack_files(Files, {[], [], [], 0, 0}).
nbl_pack_files([], {AccH, AccD, AccP, _FilePos, _PtrIndex}) ->
BinH = iolist_to_binary(lists:reverse(AccH)),
PaddingH = 8 * (16#7d0 - (byte_size(BinH) rem 16#800)),
PaddingH2 = if PaddingH =< 0 -> 16#800 + PaddingH; true -> PaddingH end,
BinD = iolist_to_binary(lists:reverse(AccD)),
PaddingD = 8 * (16#800 - (byte_size(BinD) rem 16#800)),
BinP = iolist_to_binary(lists:reverse(AccP)),
PtrSize = byte_size(BinP),
PtrArray = case PtrSize of
0 -> << >>;
_ ->
PaddingP = 8 * (16#800 - (byte_size(BinP) rem 16#800)),
<< BinP/binary, 0:PaddingP >>
end,
{<< BinH/binary, 0:PaddingH2 >>,
<< BinD/binary, 0:PaddingD >>, byte_size(BinD),
PtrArray, PtrSize};
nbl_pack_files([{data, Filename, Data, PtrList}|Tail], {AccH, AccD, AccP, FilePos, PtrIndex}) ->
ID = case filename:extension(Filename) of
".bin" -> << $S, $T, $D, 0 >>;
[$.|String] -> list_to_binary(string:to_upper(String ++ [0]))
end,
FilenamePaddingBits = 8 * (32 - length(Filename)),
DataSize = byte_size(Data),
DataPadding = 16#20 - (DataSize rem 16#20),
DataPaddingBits = 8 * DataPadding,
DataSizeWithPadding = DataSize + DataPadding,
PtrSize = 4 * length(PtrList),
BinH = << ID/binary, 16#60000000:32, 0:64, (list_to_binary(Filename))/binary, 0:FilenamePaddingBits,
FilePos:32/little, DataSize:32/little, PtrIndex:32/little, PtrSize:32/little >>,
NXIF = case filename:extension(Filename) of
".bin" -> << 0:256 >>;
_ -> nbl_pack_nxif(DataSize, PtrSize)
end,
BinH2 = << BinH/binary, NXIF/binary >>,
BinD = << Data/binary, 0:DataPaddingBits >>,
BinP = iolist_to_binary([ << Ptr:32/little >> || Ptr <- PtrList]),
nbl_pack_files(Tail, {[BinH2|AccH], [BinD|AccD], [BinP|AccP], FilePos + DataSizeWithPadding, PtrIndex + PtrSize});
nbl_pack_files([{file, Filename, PtrList}|Tail], Acc) ->
{ok, Data} = file:read_file(Filename),
nbl_pack_files([{data, Filename, Data, PtrList}|Tail], Acc).
%% @doc Return an NXIF chunk data for a specific data and pointer array size.
nbl_pack_nxif(DataSize, PtrSize) ->
DataSize2 = DataSize + 16#20,
PtrSize2 = PtrSize + 16#20 - (PtrSize rem 16#20),
<< $N, $X, $I, $F, 16#18000000:32, 16#01000000:32, 16#20000000:32,
DataSize:32/little, DataSize2:32/little, PtrSize2:32/little, 16#01000000:32 >>.