标题: 【教程】SIMS 2 MODDING信息资料库及相关讨论
stitch
离任版主
^_^


Rank: 5Rank: 5Rank: 5

精华 18
积分 5588
帖子 626

金钱 19446
经验 0
荣誉 0
互助 0

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡
【原创教程】模2 Mod 程序员参考……BHAV编程基础

其实偶也不是太懂,就在这里抛砖引玉,谨供牛人们参考。呵呵。熟悉《模拟人生2》的朋友都知道,各种Mod,包括物品,人物,衣饰和行为等等,都是以*.package的文件格式存放在downloads,savedsims和teleport目录下。Package文件,就是一组文件和代码的集合。在Package文件里,控制行为的代码,就是BHAV(Behaviour Function)。
目前流行的Package编辑工具主要有三种。
1.        SimPE。这是最常用的,应用范围最广的一种。也是我们Mod区使用和讨论的主要工具。
2.        DatGen。也是一种用户界面友好的Package编辑工具。也满有发展潜力的。
3.        DisaSim2。这种的使用者就更少了。不过据说对检验修改BHAV非常实用。

BHAV代码的结构
BHAV代码的基本结构是一系列的判断语句的树。如下图(SimPE显示的BHAV树)。

例如第4行判断,表达为语言的形式,为,
if(line_4 ==true)
    goto line_5
else
    goto line_3
当然有时判断的结果并非跳转某一行,而是返回一个真假值(出错FFFC,真值FFFD,假值FFFE)。

所有的BHAV都有相似的(HEX)格式:
64 - 文件名
12 - Header
Var - 变量1
Var - 变量2
Var - 变量n
……

每一个Header也使用相似的(HEX)格式
2 - 名鉴格式(signature, 范围0x8000到0x8009)
2 - 变量数
1 - 树的类型
1 - 参数的数量
1 - 局部变量的数量
1 - Header Flag
4 - tree version

名鉴格式有九种。
1.8000,8001&8002(变量长度:12bytes)
       2 - BHAV的(在objects.package库中的)instance(也叫OpCode)
       1 - 真值时,Goto跳转的行数
       1 - 假值时,Goto跳转的行数
       8 - 命令行(Operands)
2.8003&8004(变量长度:20bytes)
       2 - BHAV的instance
       1 - 真值时,Goto跳转的行数
       1 - 假值时,Goto跳转的行数
       16 - 命令行(Operands)
3.8005&8006(变量长度:21bytes)
       2 - BHAV的instance
       1 - 真值时,Goto跳转的行数
       1 - 假值时,Goto跳转的行数
       16 - 命令行(Operands)
4.8007(变量长度:23bytes)
       2 - BHAV的instance
       2 - 真值时,Goto跳转的行数
       2 - 假值时,Goto跳转的行数
       1 - Flag (0或1)
16 - 命令行(Operands)
5.8008&8009,夜生活的新增类型,与8007相似,区别就是Flag可以时0或1以外的其他值。

BHAV的种类
Instance 0000-00FF是基本BHAV函数(primitives)
Instance 0100-0FFF是全局BHAV函数(globals)
Instance 1000-1FFF是局部BHAV函数(locals or private)
Instance 2000-2FFF是半全局BHAV函数(semi-globals)
基本BHAV函数,是构建BHAV的基本命令。所有的BHAV,最终都是由基本BHAV函数构成,对所有的Package都有效,即所有的Package都能引用基本BHAV函数。
全局BHAV函数,由基本BHAV函数和全局BHAV函数构成。对所有的Package都有效。
局部BHAV函数,只对调用它的物品有效,即单一物品专署BHAV函数。
半全局BHAV函数,只对某一类(group)物品有效,即同类物品专署BHAV函数。要查物品所属的库(group),只要查询Package文件的GLOB(Global Data)文件。

对于物品的BHAV修改,要注意把BHAV的Group ID改成FFFFFFFF,instance ID 改成局部,即1000到1FFF。这样才能保证单一物品的修改不影响其他相关物品及整个游戏。当然如果想修改影响整个游戏的行为BHAV,例如吸血鬼白天活动的MOD,就不用改Group ID和Instance ID了。

如何引用BHAV函数
有4种办法引用BHAV函数。
1.        在现有的BHAV中引用。
2.        使用菜单函数(TTAB,Pie menu function),即点击物品或人物时弹出的菜单选项。在TTAB中,增加一行,填入要引用的BHAV的opcode。一般每行TTAB要引用两个BHAV,一个是行动指令(Action Field),另一个是条件指令(Guardian)。比如想引用准备早餐-蛋糕,行动指令就是作蛋糕,可是作蛋糕要求小人有比较高的烹饪值,条件指令就是检查小人的烹饪值。 当条件指令不满足时,行动指令的选项就不会出现在弹出菜单里。
3.        使用物品功能函数调用BHAV。物品功能函数(OBJf,Object Function),不像菜单函数那样互动的,而是游戏自动执行的。每个命令行也包括条件指令和行动指令。
4.        修改覆盖原有的BHAV。

BHAV引用的常数
BHAV引用的常数,一般存储在BCON文件里。有时MOD的修改,并不需要改BHAV,只要改BCON中的常数就可以非常容易的实现,而且也比直接改BHAV更安全。

最常用的BHAV函数

顶部
iloveunix
游侠荣誉会员
猪头帮主
精灵族[P*]风暴祭祀



Rank: 5Rank: 5Rank: 5

精华 15
积分 5666
帖子 3887

金钱 4020
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

谢谢






顶部
iloveunix
游侠荣誉会员
猪头帮主
精灵族[P*]风暴祭祀



Rank: 5Rank: 5Rank: 5

精华 15
积分 5666
帖子 3887

金钱 4020
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!
这个是我自己瞎弄的自己看着舒服而已:P

struct BHAV_stitch{//BHAV 文件数据结构
char Name[64];//文件名
char Header[12];//文件头
char Var[];//变量1.....n
}
struct Header_stitch{//BHAV 文件头数据结构
char Signature[2];//名鉴格式(signature, 范围0x8000到0x80009)
char VarNum[2];//变量数
char TreeType;//树的类型
char ParamNum;//参数的数量
char LocalVarNum;//局部变量的数量
char HeaderFlag;//文件头标志
char TreeVersion;//树版本号
}

Instance的种类
Instance 0000-00FF是基本BHAV函数(primitives)==============API INSTANCE
Instance 0100-0FFF是全局BHAV函数(globals)=================GLOBAL INSTANCE
Instance 1000-1FFF是局部BHAV函数(locals or private)=======SPECIALOBJECT INSTANCE
Instance 2000-2FFF是半全局BHAV函数(semi-globals)=========GROUPOBJECTS INSTANCE

struct Evaluate_stitch{//最常用的BHAV函数(opcode 0x0002)基本数据结构
short A;//变量A
short B;//变量B
char Flag;//Flag
char AType;//变量A类型
char OperateCode;//操作符
char BType;//变量B类型
}






顶部
iloveunix
游侠荣誉会员
猪头帮主
精灵族[P*]风暴祭祀



Rank: 5Rank: 5Rank: 5

精华 15
积分 5666
帖子 3887

金钱 4020
经验 0
荣誉 0
互助 0

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

2 - A的类别下的类型
2 - B的数值
1 - flag
1 - A的变量类别
1 - 操作符
1 - B的类别

==============
颠倒了
==============
2 - A的类别下的类型
2 - B的数值
1 - flag
1 - 操作符
1 - A的变量类别
1 - B的类别






顶部
iloveunix
游侠荣誉会员
猪头帮主
精灵族[P*]风暴祭祀



Rank: 5Rank: 5Rank: 5

精华 15
积分 5666
帖子 3887

金钱 4020
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。
MTS2的资料库之一========》Packages

======================
原贴址:
http://www1.modthesims2.com/wiki/Packages
======================
以Set Vapire Nighttime Awake BHAV为图示例子
======================
Package File Format

This will be Broken into 3 parts. DATS/Holes/Records, Compression, and DIR files



Format of Simcity4 Archive data files


Most simcity Data is as you probably know stored in various types of archive files that all have the same internal format such as DAT, SC4, SC4lot, etc. This format is proprietary to maxis and has been used in the sims online as well as this one.
Header (96 bytes)
File 1
File 2
File n
Index Entry 1 (20 bytes)
Index Entry 2
Index Entry n

Header first, individual files following with no filenames and a small file header area at the beginning of each followed by an index of all the files in the archive at 20 bytes per entry.

Header:

Offset 00 - Identifier (DBPF - the type of dat)
Offset 04 - Version Major (1 in SC4/Ts2 Dats)
Offset 08 - Version Minor (0 in sc4 dats, 1 in most TS2 packages)
Offset 12 - 3 DWORDS of unused data. RESERVED for maxis use.
Offset 24 - Date Created in Hex (Unused in Version 1.1)
Offset 28 - Date Modified in Hex (Unused in Version 1.1)
Offset 32 - Index Type/Version (Always 7 in SC4/TS2 dats)
Offset 36 - Number of entries in the index
Offset 40 - Location of first index entry
Offset 44 - Size of index
Offset 48 - Number of Hole entries in the Hole Record
Offset 52 - Location of the hole Record
Offset 56 - Size of the hole Record
Offset 60 - Number of Instances in Index (0x01 or 0x02; Version 1.1+ in TS2 only)
Offset 64 - 32 Bytes reserved for Future Use in other versions.

File: (File starts at offset 0 if uncompressed or 9 if compressed with this header)

Offset 00 - Size of file
Offset 04 - Compression signature (if file is compressed or not)
Offset 06 - Uncompressed filesize (Big Endian)
Offset 09 - Start of compressed/uncompressed file data


The size of an index entry with 1 Instance is 20 bytes, like this:

Offset 00 - Type ID (main type of file. picture, texture, model etc)
Offset 04 - Group ID (group of the file by purpose or type)
Offset 08 - Instance ID (marker used by the format for finding a specific file)
Offset 12 - Location of the file in the archive
Offset 16 - Size of the file

New 2 Instance Index Entry 24 bytes

Offset 00 - Type ID (main type of file. picture, texture, model etc)
Offset 04 - Group ID (group of the file by purpose or type)
Offset 08 - Instance ID (marker used by the format for finding a specific file)
Offset 12 - Instance2/Resource ID
Offset 16 - Location of the file in the archive
Offset 20 - Size of the file


One of the problems with this dat format is that filenames and filetypes are not preserved. Therefore the only way of knowing the type of file is by its IDS and then you don't have a true extension. It is for this reason that some of the filetypes to follow have names created by us instead of the true Maxis names. They simply aren't available.

A Hole record contains the location and size of all holes in a DAt file. Its format is as follows

(repeating)
DWORD - Hole Location
DWORD - Hole size

a Hole is simply garbage data that can be filled in with useful data at a later point



Compression

The idea behind the compression is to reuse previously decoded strings. For example, if the word "heureka" occurs twice in a file, the second occurence would be encoded by pointing to the first.

The compression is done by defining control characters that tells three things:


How many characters of plain text that follows that should be appended to the output.
How many characters that should be read from the already decoded text (and appended to the output)
At which offset in the aldready decoded text to read the characters.

Thus, the algorithm to decompress these files goes like this:

Read file size at offset 0
Seek to offset 9
while not end of file is reached do
{

Read next control character.
(Depending on control character read 0-3 more bytes that are a part of the control character.)
Figure out how many characters that should be read and from where by inspecting the control character.
Read 0-n characters from source and append them to the output.
Copy 0-n characters from somewhere in the output to the end of the output.
}

There are 4 types of control characters which are used with different restrictions of how many characters that can be read and from how far behind these can be read. The following conventions are used to describe them:

CC length - Length of control character.
Num plain text - Number of chars immediately after the control character that should be read and appended to output.
Num to copy - Number of chars that should be copied from somewhere in the already decoded output and added to the end of the output.
Copy offset - Where to start reading characters when copying from somewhere in the already decoded output.
This is given as an offset from the current end of the output buffer, i.e. an offset of 0 means that you should copy the last character in the output and append it to the output. And offset of 1 means that you should copy the second-to-last character.
byte0 - first byte of control character.
Bits - Bits of the control character. p = num plain text, c = num to copy, o = copy offset, i = identifier.

Note: It can sometimes be confusing when a control character states that you should copy for example 10 characters 5 steps from the end of the output. Clearly, you cannot read more than 5 characters before you reach the end of the buffer. The solution is to read and write one character at the time. Each time you read a character you copy it to the end thereby increasing the size of the output. By doing this, even offset 0 is possible and would result in duplicating the last character a number of times. This is utilized by the compression to recreate repeating text, for example bars of repeating dashes


0xE0 - 0xFF

CC length: 1 byte
Num plain text: ((byte0 & 0x1F) < < 2 ) + 4
Num to copy: 0
Copy offset: -

Bits: 111ppppp
Num plain text limit: 4-128
Num to copy limit: 0
Maximum Offset: -

This is the simplest form of control character. The only thing it does is telling how many plain text characters that follows. The formula for this is: (C - 0x7F) * 4. Thus a value of 0xE0 means that you should read 4 characters of plain text and append to the output.


0x00 - 0x7F

CC length: 2 bytes
Num plain text: byte0 & 0x03
Num to copy: ( (byte0 & 0x1C) > > 2) + 3
Copy offset: ( (byte0 & 0x60) < < 3) + byte1 + 1

Bits: 0oocccpp oooooooo
Num plain text limit: 0-3
Num to copy limit: 3-11
Maximum Offset: 1023


0x80 - 0xBF

CC length: 3 bytes
Num plain text: ((byte1 & 0xC0) > > 6 ) & 0x03
Num to copy: (byte0 & 0x3F) + 4
Copy offset: ( (byte1 & 0x3F) < < 8 ) + byte2 + 1

Bits: 10cccccc ppoooooo oooooooo

Num plain text limit: 0-3
Num to copy limit: 4-67
Maximum Offset: 16383


0xC0 - 0xDF

CC length: 4 bytes
Num plain text: byte0 & 0x03
Num to copy: ( (byte0 & 0x1C) < < 6 ) + byte3 + 5
Copy offset: (byte1 < < 8) + byte2

Bits: 110cccpp oooooooo oooooooo cccccccc

Num plain text limit: 0-3
Num to copy limit: 5-2047
Maximum Offset: 65535

Note: Sims2 uses a slightly different variation here:
CC length: 4 bytes
Num plain text: byte0 & 0x03
Num to copy: ( (byte0 & 0x0C) < < 6 ) + byte3 + 5
Copy offset: ((byte0 & 0x10) < < 12 ) + (byte1 < < 8 ) + byte2 + 1

Bits: 110occpp oooooooo oooooooo cccccccc

Num plain text limit: 0-3
Num to copy limit: 5-1028
Maximum Offset: 131072




Directory Files explained

Directory files are one of the newer filetypes I found about the beginning of May. Their purpose is to spead up the loading of a DAT file by showing exactly what is compressed inside it. They are directories of all the compressed files in an archive. This luckily makes their structure fairly simple. 4 DWORDS repeated over and over

(Repeated Chunk)

DWORD - Type ID of the file
DWORD - Group ID of the file
DWORD - Instance ID of the file
DWORD (only in new index format dbpfs) - Instance2/Resource ID
DWORD - Size of the decompressed file in Hex

These files are found as DIR/Directory by the reader and are automatically modified by it during changes to dat files.

It is HIGHLY reccommended that you modify the Directory after editing any compressed file before saving the dat if you are working manually in Hex or making your own program.

If identifying Directory files manually by Hex, their Type ID in the index will be (EF 1E 6B E8)






顶部
iloveunix
游侠荣誉会员
猪头帮主
精灵族[P*]风暴祭祀



Rank: 5Rank: 5Rank: 5

精华 15
积分 5666
帖子 3887

金钱 4020
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!
Sims2Skin文件格式

原文贴址:
http://www1.modthesims2.com/wiki/Sims2Skin
转自网站:MTS2
First there is some header info...

18 - Header (Sims2 Packager 1.0)
4 - Data Offset

Then comes the XML data...

<?xml version="1.0" encoding="UTF-8"?>
<Sims2Package type="assets">
<!-- START REPEATABLE -->
<PackagedFile>
<Name>starter.package</Name>
<Length>8903470</Length>
<Type>part</Type>
<Offset>0</Offset>
<Description>Something here</Description>
</PackagedFile>
<!-- END REPEATABLE -->
</Sims2Package>

Following this comes the file data according to the offset and size info in the XML header. Also, the offset is relative to the end of the XML data.

There are two possible Types, part and sim, however, I don't know what's the difference.

Obviously the "start/stop repeatable" tags don't appear in the file, thats just for your benefit.
=============
sims2 Packer生成sims2skin文件
sims2skin文件实际就是把*.package封装一下
加个sims2 Packer标签,然后可直接双击调用sims2 Packer将封装的*.package解压到相应的目录
sims2skin文件格式分3个部分
First there is some header info... 一个sims2 Packer标签
Then comes the XML data... 一个XML文件
Following this comes the file data一个PACKAGE
然后这3个部分被整合到一个文件
就成了SIMS2SKIN






顶部
火奴儿
游侠会员



Rank: 1

精华 0
积分 17
帖子 56

金钱 49
经验 0
荣誉 0
互助 0

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

【天啦】 【天啦】 【天啦】 好复杂啊~我会慢慢研究的~

顶部
lLOVEUNIX
游侠会员

哈比族 呓语之魔冢



Rank: 1

精华 0
积分 152
帖子 508

金钱 267
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。
Sims2Pack文件格式

原文贴址:
http://www1.modthesims2.com/wiki/Sims2Pack
转自网站:MTS2
First there is some header info...

18 - Header (Sims2 Packager 1.0)
4 - Data Offset

Then comes the XML data...

<?xml version="1.0" encoding="UTF-8"?>
<Sims2Package type="Object">
<GameVersion>2141707388.153.1</GameVersion>
<!-- START REPEATABLE -->
<PackagedFile>
<Name><![CDATA[XXXfilenameXXX]]></Name>
<Crc>552674faeebf57f3a8f0550f690ac902</Crc>
<Length>8903470</Length>
<Type>Object</Type>
<Offset>0</Offset>
<Description><![CDATA[XXXdescriptionXXX]]></Description>
</PackagedFile>
<!-- END REPEATABLE -->
</Sims2Package>

Following this comes the file data according to the offset and size info in the XML header. Also, the offset is relative to the end of the XML data.


Obviously the "start/stop repeatable" tags don't appear in the file, thats just for your benefit. This archive format is used for object downloads from www.TheSims2.com, and as such contains *.package files.

====================
其实和SIMS2KIN一个类型的解释
不罗嗦了

顶部
lLOVEUNIX
游侠会员

哈比族 呓语之魔冢



Rank: 1

精华 0
积分 152
帖子 508

金钱 267
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!
movie文件格式

原文贴址:
http://www1.modthesims2.com/wiki/Movie
转自网站:MTS2
From Simcity 4

--------------------------------------------------------------------------------

MAD video is the format of Simcity4's videos. Not really anything else to say about it. Its taken us a long time to really get started on this though, but here we are

There are video and audio blocks
The video is EA specific type
The audio is EA ASF STR Audio
The whole format is really a one block video one block audio repeat.

It has the following structure


--------------------------------------------------------------------------------
Video blocks - Hayly,Darkmatter,Karybdis

--------------------------------------------------------------------------------
Header:

DWORD - MAD* - Identifier of Block where * is a unique block type identifier :
DWORD - Size of the block
DWORD - Unknown
WORD - Suggested Buffer (in Bytes)
WORD - Frames per second (in ms delay per frame)
WORD - Pixel width of the block
WORD - Pixel height of the block
BYTE - Unknown
BYTE - Unknown
WORD - Unknown

--MAD TYPES
k = Mad pixel encoding type K. (Has 15 byte Entries., or 10 byte, 20 byte, rept)
m = Mad Pixel encoding type M. (Has 18 byte Entries.)
e = Mad Block Type E (18 byte entries)


--------------------------------------------------------------------------------
Video Data - Each video block has readable data blocks with a size dependant on its identifier (k,m). The codec breakdown is unknown, so we cant view the movies yet


= 1. .ASF/.STR Music Files (MAD Audio Blocks) - Valery V. Anisimovsky

=
The music in many new Electronic Arts games is in .ASF stand-alone files
(sometimes ASF files have extension .STR). These files have the block
structure analoguous to RIFF. Namely, these files are divided into blocks
(without any global file header like RIFFs have). Each block has the
following header:

struct ASFBlockHeader
{
  char        szBlockID[4];
  DWORD dwSize;
};
szBlockID -- string ID for the block.

dwSize -- size of the block (in bytes) INCLUDING this header.

Further I'll describe the contents of blocks of all block types in .ASF file.

When I say "block begins with..." that means "the contents of that
block (which begin just after ASFBlockHeader) begin with...".
Quoted strings are block IDs.

"SCHl": header block. This is the first block in ASF.
In the most of files this block begins with the ID string "PT\0\0" (or number
0x50540000). Further goes the PT header data which describes audio data in
the file. This PT header should be parsed rather than just read as a simple
structure. Here I give the parsing code. These functions use fread() and fseek()
stdio functions.

// first of all, we need a function which reads a small (variable) number
// bytes and composes a DWORD of them. Note that such DWORD will be a kind
// of big-endian (Motorola) stored, e.g. 3 consecutive bytes 0x12 0x34 0x56
// will give a DWORD 0x00123456.
DWORD ReadBytes(FILE* file, BYTE count)
{
  BYTE        i, byte;
  DWORD result;

  result=0L;
  for (i=0;i<count; i+ + )
  {
        fread(&byte,sizeof(BYTE),1,file);
        result<<=8;
        result+=byte;
  }

  return result;
}

// these will be set by ParsePTHeader
DWORD dwSampleRate;
DWORD dwChannels;
DWORD dwCompression;
DWORD dwNumSamples;
DWORD dwDataStart;
DWORD dwLoopOffset;
DWORD dwLoopLength;
DWORD dwBytesPerSample;
BYTE  bSplit;
BYTE  bSplitCompression;

// Here goes the parser itself
// This function assumes that the current file pointer is set to the
// start of PT header data, that is, just after PT string ID "PT\0\0"
void ParsePTHeader(FILE* file)
{
  BYTE byte;
  BOOL bInHeader, bInSubHeader;

  bInHeader=TRUE;
  while (bInHeader)
  {
        fread(&byte,sizeof(BYTE),1,file);
        switch (byte) // parse header code
        {
          case 0xFF: // end of header
           bInHeader=FALSE;
          case 0xFE: // skip
          case 0xFC: // skip
           break;
          case 0xFD: // subheader starts...
           bInSubHeader=TRUE;
           while (bInSubHeader)
           {
             fread(&byte,sizeof(BYTE),1,file);
             switch (byte) // parse subheader code
             {
               case 0x82:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwChannels=ReadBytes(file,byte);
                    break;
               case 0x83:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwCompression=ReadBytes(file,byte);
                    break;
               case 0x84:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwSampleRate=ReadBytes(file,byte);
                    break;
               case 0x85:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwNumSamples=ReadBytes(file,byte);
                    break;
               case 0x86:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwLoopOffset=ReadBytes(file,byte);
                    break;
               case 0x87:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwLoopLength=ReadBytes(file,byte);
                    break;
               case 0x88:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwDataStart=ReadBytes(file,byte);
                    break;
               case 0x92:
                    fread(&byte,sizeof(BYTE),1,file);
                    dwBytesPerSample=ReadBytes(file,byte);
                    break;
               case 0x80: // ???
                    fread(&byte,sizeof(BYTE),1,file);
                    bSplit=ReadBytes(file,byte);
                    break;
               case 0xA0: // ???
                    fread(&byte,sizeof(BYTE),1,file);
                    bSplitCompression=ReadBytes(file,byte);
                    break;
               case 0xFF:
                    subflag=FALSE;
                    flag=FALSE;
                    break;
               case 0x8A: // end of subheader
                    bInSubHeader=FALSE;
               default: // ???
                    fread(&byte,sizeof(BYTE),1,file);
                    fseek(file,byte,SEEK_CUR);
             }
           }
           break;
          default:
           fread(&byte,sizeof(BYTE),1,file);
           if (byte==0xFF)
              fseek(file,4,SEEK_CUR);
           fseek(file,byte,SEEK_CUR);
        }
  }
}
dwSampleRate -- sample rate for the file. Note that headers of most of
ASFs/MUSes I've seen DO NOT contain sample rate subheader section. Currently
I just set sample rate for such files to the default: 22050 Hz. It seems to
work okay.

dwChannels -- number of channels for the file: 1 for mono, 2 for stereo.
If this is NOT set by ParsePTHeader, then you may use the default: stereo.

dwCompression -- Compression tag. If this is 0x00, then no compression is
used and audio data is signed 16-bit PCM. If this is 0x07, the audio data is
compressed with EA ADPCM algorithm. Please read the next section for the
description of EA ADPCM decompression scheme. In some files this tag is
omitted -- I use 0x00 (no compression) for them.

dwNumSamples -- number of samples in the file.

dwDataStart -- in ASF files this's not used.

dwLoopOffset -- offset when looping (from start of sound part).

dwLoopLength -- length when looping.

dwBytesPerSample -- bytes per sample (Default is 2). Divide this by
dwChannels to get resolution of sound data.

bSplit -- this looks like to be 0x01 for files using "split" SCDl blocks
(see below). If this subheader field is absent, the file uses "normal"
(interleaved) SCDl blocks.

bSplitCompression -- this looks like to be 0x08 for files using non-compressed
"split" SCDl blocks. If this subheader field is absent in the file using
"split" SCDls, the file uses EA ADPCM compression. This subheader field
should not appear in a file using "normal" (interleaved) SCDls.

"SCCl": count block. This block goes after "SCHl" and contains one DWORD
value which is a number of "SCDl" data blocks in ASF file.

"SCDl": data block. These blocks contain audio data. Depending on the
parameters set in the header (see above) SCDl block may contain compressed
(by EA ADPCM or IMA ADPCM) or non-compressed audio data and the data itself
may be interleaved or split (see below).

If no compression is used and the file does not use "split" SCDl blocks,
SCDl block begins with a DWORD value which is the number of samples in this
block and after that comes signed 16-bit PCM data, in the interleaved form:
LRLR...LR (L and R are 16-bit sample values for left and right channels).

Hereafter by "chunk" I mean the audio data in the "SCDl" data block, that is,
compressed/non-compressed data which starts after chunk header.

In the newer EA games (NHL'2000/NBA'2000/FIFA'99'2000/NFS5) non-compressed
"split" SCDl blocks are used. These blocks begin with a chunk header:

struct ASFSplitPCMChunkHeader
{
  DWORD dwOutSize;
  DWORD dwLeftChannelOffset;
  DWORD dwRightChannelOffset;
}
dwOutSize -- size of audio data in this chunk (in samples).

dwLeftChannelOffset, dwRightChannelOffset -- offsets to PCM data for
left and right channels, relative to the byte which immediately follows
ASFSplitPCMChunkHeader structure. E.g. for left channel this offset is zero
-- the data starts immediately after this structure.

After this structure comes PCM data for stereo wavestream and it's not
interleaved (LRLRLR...), but it's split: first go sample values for left
channel, then -- for right channel, that is the layout is LL...LRR...R.

If EA ADPCM (or IMA ADPCM) compression is used, but the file does not use
"split" SCDls, each SCDl block begins with a chunk header:

struct ASFChunkHeader
{
  DWORD dwOutSize;
  SHORT lCurSampleLeft;
  SHORT lPrevSampleLeft;
  SHORT lCurSampleRight;
  SHORT lPrevSampleRight;
};
dwOutSize -- size of decompressed audio data in this chunk (in samples).

lCurSampleLeft, lCurSampleRight, lPrevSampleLeft, lPrevSampleRight are initial
values for EA ADPCM decompression routine for this data block (for left and right
channels respectively). I'll describe the usage of these further when I get to
EA ADPCM decompression scheme.

Note that the structure above is ONLY for stereo files. For mono there're
just no lCurSampleRight, lPrevSampleRight fields.

If IMA ADPCM compression is used, the meanings of some chunk header fields
are different -- see my EA-ASF.TXT specs for details.

After this chunk header the compressed data comes. See the next section for
EA ADPCM decompression scheme description.

If EA ADPCM (or IMA ADPCM) compression is used and the file uses "split" SCDls,
each SCDl block begins with a different chunk header:

struct ASFSplitChunkHeader
{
  DWORD dwOutSize;
  DWORD dwLeftChannelOffset;
  DWORD dwRightChannelOffset;
};
SHORT lCurSampleLeft;
SHORT lPrevSampleLeft;
BYTE  bLeftChannelData[]; // compressed data for left channel goes here...
SHORT lCurSampleRight;
SHORT lPrevSampleRight;
BYTE  bRightChannelData[]; // compressed data for right channel goes here...
dwOutSize -- size of decompressed audio data in this chunk (in samples).

dwLeftChannelOffset, dwRightChannelOffset -- offsets to compressed data for
left and right channels, relative to the byte which immediately follows
ASFSplitChunkHeader structure. E.g. for left channel this offset is zero --
the data starts immediately after this structure.

lCurSampleLeft, lCurSampleRight, lPrevSampleLeft, lPrevSampleRight have the
same meaning as above, but note that these values are SHORTs.

So, use mono decoder for each channel data and then create normal LRLR...
stereo waveform before outputting.
Such (newer) files may be separated from the others by presence of 0x80 type
section in PT header (the value stored in the section is 0x01 for such files).
Some of such files also do not contain compression type (0x83) section in
their PT header.

"SCLl": loop block. This block defines looping point for the song. It
contains only DWORD value, which is the looping jump position (in samples)
relative to the start of the song. You should make the jump just when you
encounter this block.

"SCEl": end block. This block indicates the end of audio stream.

Note that in some games audio files are contained within game resources. As
a rule, such resources are not compressed/encrypted, so you may just search
for ASF file signature (e.g. "SCHl") and this will mark the beginning of audio
stream, while "SCEl" block marks the end of that stream.


2. EA ADPCM Decompression Algorithm


During the decompression four LONG variables must be maintained for stereo
stream: lCurSampleLeft, lCurSampleRight, lPrevSampleLeft, lPrevSampleRight
and two -- for mono stream: lCurSample, lPrevSample. At the beginning of each
"SCDl" data block you must initialize these variables using the values in
ASFChunkHeader.
Note that LONG here is signed.

Here's the code which decompresses one "SCDl" block of EA ADPCM compressed
stereo stream.

BYTE  InputBuffer[InputBufferSize]; // buffer containing audio data of "SCDl" block
BYTE  bInput;
DWORD dwOutSize; // outsize value from the ASFChunkHeader
DWORD i, bCount, sCount;
LONG  c1left,c2left,c1right,c2right,left,right;
BYTE  dleft,dright;

DWORD dwSubOutSize=0x1c;

i=0;

// process integral number of (dwSubOutSize) samples
for (bCount=0;bCount<(dwOutSize/dwSubOutSize);bCount++)
{
  bInput=InputBuffer[i++];
  c1left=EATable[HINIBBLE(bInput)];   // predictor coeffs for left channel
  c2left=EATable[HINIBBLE(bInput)+4];
  c1right=EATable[LONIBBLE(bInput)];  // predictor coeffs for right channel
  c2right=EATable[LONIBBLE(bInput)+4];
  bInput=InputBuffer[i++];
  dleft=HINIBBLE(bInput)+8;   // shift value for left channel
  dright=LONIBBLE(bInput)+8;  // shift value for right channel
  for (sCount=0;sCount<dwSubOutSize;sCount++)
  {
        bInput=InputBuffer[i++];
        left=HINIBBLE(bInput);  // HIGHER nibble for left channel
        right=LONIBBLE(bInput); // LOWER nibble for right channel
        left=(left<<0x1c)>>dleft;
        right=(right<<0x1c)>>dright;
        left=(left+lCurSampleLeft*c1left+lPrevSampleLeft*c2left+0x80)>>8;
        right=(right+lCurSampleRight*c1right+lPrevSampleRight*c2right+0x80)>>8;
        left=Clip16BitSample(left);
        right=Clip16BitSample(right);
        lPrevSampleLeft=lCurSampleLeft;
        lCurSampleLeft=left;
        lPrevSampleRight=lCurSampleRight;
        lCurSampleRight=right;

        // Now we've got lCurSampleLeft and lCurSampleRight which form one stereo
        // sample and all is set for the next input byte...
        Output((SHORT)lCurSampleLeft,(SHORT)lCurSampleRight); // send the sample to output
  }
}

// process the rest (if any)
if ((dwOutSize % dwSubOutSize) != 0)
{
  bInput=InputBuffer[i++];
  c1left=EATable[HINIBBLE(bInput)];   // predictor coeffs for left channel
  c2left=EATable[HINIBBLE(bInput)+4];
  c1right=EATable[LONIBBLE(bInput)];  // predictor coeffs for right channel
  c2right=EATable[LONIBBLE(bInput)+4];
  bInput=InputBuffer[i++];
  dleft=HINIBBLE(bInput)+8;   // shift value for left channel
  dright=LONIBBLE(bInput)+8;  // shift value for right channel
  for (sCount=0;sCount<(dwOutSize % dwSubOutSize);sCount++)
  {
        bInput=InputBuffer[i++];
        left=HINIBBLE(bInput);  // HIGHER nibble for left channel
        right=LONIBBLE(bInput); // LOWER nibble for right channel
        left=(left<<0x1c)>>dleft;
        right=(right<<0x1c)>>dright;
        left=(left+lCurSampleLeft*c1left+lPrevSampleLeft*c2left+0x80)>>8;
        right=(right+lCurSampleRight*c1right+lPrevSampleRight*c2right+0x80)>>8;
        left=Clip16BitSample(left);
        right=Clip16BitSample(right);
        lPrevSampleLeft=lCurSampleLeft;
        lCurSampleLeft=left;
        lPrevSampleRight=lCurSampleRight;
        lCurSampleRight=right;

        // Now we've got lCurSampleLeft and lCurSampleRight which form one stereo
        // sample and all is set for the next input byte...
        Output((SHORT)lCurSampleLeft,(SHORT)lCurSampleRight); // send the sample to output
  }
}
HINIBBLE and LONIBBLE are higher and lower 4-bit nibbles:
#define HINIBBLE(byte) ((byte) >> 4)
#define LONIBBLE(byte) ((byte) & 0x0F)
Note that depending on your compiler you may need to use additional nibble
separation in these defines, e.g. (((byte) >> 4) & 0x0F).

EATable is the table given in the next section of this document.

Output() is just a placeholder for any action you would like to perform for
decompressed sample value.

Clip16BitSample is quite evident:
LONG Clip16BitSample(LONG sample)
{
  if (sample>32767)
         return 32767;
  else if (sample<-32768)
         return (-32768);
  else
         return sample;
}
As to mono sound, it's just analoguous: dwSubOutSize=0x0E for mono and
you should get predictor coeffs and shift from one byte:
bInput=InputBuffer[i++];
c1=EATable[HINIBBLE(bInput)];        // predictor coeffs
c2=EATable[HINIBBLE(bInput)+4];
d=LONIBBLE(bInput)+8;  // shift value
And also you should process HIGHER nibble of the input byte first and then
LOWER nibble for mono sound.

Of course, this decompression routine may be greatly optimized.


3. EA ADPCM Table

LONG EATable[]=
{
  0x00000000,
  0x000000F0,
  0x000001CC,
  0x00000188,
  0x00000000,
  0x00000000,
  0xFFFFFF30,
  0xFFFFFF24,
  0x00000000,
  0x00000001,
  0x00000003,
  0x00000004,
  0x00000007,
  0x00000008,
  0x0000000A,
  0x0000000B,
  0x00000000,
  0xFFFFFFFF,
  0xFFFFFFFD,
  0xFFFFFFFC
};

顶部
comics89
游侠会员
SIMS整容师学徒


Rank: 1

精华 0
积分 144
帖子 479

金钱 745
经验 0
荣誉 0
互助 0

来自 上海
超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

挖!,不懂,不懂,不懂,看的我眼都花了,这有什么用处吗?你们真厉害!!!

顶部
sdyxivg
游侠会员


Rank: 1

精华 0
积分 21
帖子 71

金钱 121
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

两个字评价
不懂!!!!!!!呀!!!!!!!!!!!!!!!!!!!!!!!

顶部
wengjiazhen
游侠会员



Rank: 1

精华 0
积分 1
帖子 2

金钱 2
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!

这些东西应该是开发人员研究的吧!对我们有用吗?

顶部
janka
游侠会员


Rank: 1

精华 0
积分 26
帖子 85

金钱 178
经验 0
荣誉 0
互助 0

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

过于专业了,竟然说“其实偶也不是太懂”
……

顶部
Γ8.誀鮗⑧
游侠会员


Rank: 1

精华 0
积分 1
帖子 2

金钱 32
经验 0
荣誉 0
互助 0

来自 安徽
youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

[晕死] [晕死] 好晕啊,看得我眼都花拉...郁闷的,研究了好几天,还是没有全弄明白是啥意思的.


55555555555555555555555555555

顶部
miyuhyde
游侠会员



Rank: 1

精华 0
积分 17
帖子 58

金钱 63
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!

本人眼花+头晕中。。。。痛苦哇!!我想自己做小人玩。。5555555

顶部
Godkind
游侠会员


Rank: 1

精华 0
积分 312
帖子 908

金钱 1107
经验 0
荣誉 0
互助 8

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

好东西,顶了…………………………………………………………………………





Godkind/Qhumbah/&/
——————————
点击下面这个链接安装RealLink软件
运行RealLink后搜“&”或“123597949"
在“免费文件夹”找“模拟人生2”下载
届时各位将已连入我的电脑(别趁机害我)
——————————
http://login.reallink.cn/reg/reg_rl.asp?id=123597949
顶部
alshmir
游侠会员



Rank: 1

精华 0
积分 9
帖子 31

金钱 61
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

这就是传说中的源代码吗?何止是复杂啊。简直是复杂到一定程度了

顶部
APPE99
游侠会员



Rank: 1

精华 0
积分 13
帖子 43

金钱 74
经验 0
荣誉 0
互助 0

参与论坛活动,赚取LTB!

看不懂!!!!我还是玩我的游戏好了!

顶部
jasoncici
游侠会员



Rank: 1

精华 0
积分 2
帖子 8

金钱 38
经验 0
荣誉 0
互助 0

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

这对玩游戏有什么帮助吗?  我什么都看不明白!   再说什么????????  谁能用比较简单的语言说说明白??

顶部
tmt747
游侠会员



Rank: 1

精华 0
积分 36
帖子 120

金钱 152
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

。。。。。。看来我想开的游戏是越来越远了~~~~~~~ [汗水]

顶部
xiyao
游侠会员
SIMS高级设计师


Rank: 1

精华 0
积分 251
帖子 704

金钱 1953
经验 0
荣誉 0
互助 8

参与论坛活动,赚取LTB!

真正的精品。。。。
可是英文版的看不懂,stitch 写的很清晰,但是内容很少,还有谁会bhav???想学啊。。。。。





顶部
xiyao
游侠会员
SIMS高级设计师


Rank: 1

精华 0
积分 251
帖子 704

金钱 1953
经验 0
荣誉 0
互助 8

超人气网页游戏《游侠·兵临城下》2号服务器将于11月20日下午3点火热推出,点击领取新手卡

我稍微解释一下吧。。。
我们对于玩sims2,已经不再满足于游戏自带的内容,不断有玩家制作出新的自定义的东东。。
这些自定义的东西,我大致分为两大类。

第一类,模型类。。这一类,在国内已经有比较多的教程,和相当一部分掌握。。。他们可以通过3d软件和simpe的帮助下,制作出很多新的,漂亮的头发,家具,首饰,衣服模型(new mesh)。

第二类,bhav类,这类与上一类不同,他修改研究的是游戏代码。通过修改bhav我可以修改小人或者物品的属性,随心所欲控制小人的行为。。。等等。。。于是,通过修改bhav就能造出各类控制器,比方说动作盒子,比方说催生器。。

以上是我个人的理解,有误请指出。。。。





顶部
老虎的妈妈
游侠会员



Rank: 1

精华 0
积分 68
帖子 227

金钱 259
经验 0
荣誉 0
互助 0

youki 系统正式开放!可方便检索和录入大量有价值的游戏相关信息。

天呐,看不懂。我只是想把小人冬天的衣服改多点啦,不用那么复杂吧

顶部



www.netshowbbs.com game.ali213.net
我们每天在进步 游侠游戏社区 游侠网


当前时区 GMT+8, 现在时间是 2008-11-19 14:17
增值电信业务经营许可证 沪B2-20050044

Powered by Discuz! 5.5.0  © 2001-2007 Comsenz Inc.
清除 Cookies - 联系我们 - 游侠NETSHOW论坛 - Archiver - WAP