Test: Load c&c terrain tiles
This commit is contained in:
@@ -29,27 +29,52 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
public Terrain( Stream stream )
|
public Terrain( Stream stream )
|
||||||
{
|
{
|
||||||
int Width, Height;
|
int Width, Height, IndexEnd, IndexStart;
|
||||||
|
uint ImgStart;
|
||||||
|
// Try loading as a cnc .tem
|
||||||
BinaryReader reader = new BinaryReader( stream );
|
BinaryReader reader = new BinaryReader( stream );
|
||||||
Width = reader.ReadUInt16();
|
Width = reader.ReadUInt16();
|
||||||
Height = reader.ReadUInt16();
|
Height = reader.ReadUInt16();
|
||||||
|
|
||||||
if( Width != 24 || Height != 24 )
|
if( Width != 24 || Height != 24 )
|
||||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||||
|
|
||||||
/*NumTiles = */reader.ReadUInt16();
|
/*NumTiles = */reader.ReadUInt16();
|
||||||
reader.ReadUInt16();
|
/*Zero1 = */reader.ReadUInt16();
|
||||||
/*XDim = */reader.ReadUInt16();
|
/*uint Size = */reader.ReadUInt32();
|
||||||
/*YDim = */reader.ReadUInt16();
|
ImgStart = reader.ReadUInt32();
|
||||||
/*uint FileSize = */reader.ReadUInt32();
|
/*Zero2 = */reader.ReadUInt32();
|
||||||
uint ImgStart = reader.ReadUInt32();
|
|
||||||
reader.ReadUInt32();
|
if (reader.ReadUInt16() == 65535) // ID1 = FFFFh for cnc
|
||||||
reader.ReadUInt32();
|
{
|
||||||
int IndexEnd = reader.ReadInt32();
|
/*ID2 = */reader.ReadUInt16();
|
||||||
reader.ReadUInt32();
|
IndexEnd = reader.ReadInt32();
|
||||||
int IndexStart = reader.ReadInt32();
|
IndexStart = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
else // Load as a ra .tem
|
||||||
|
{
|
||||||
|
stream.Position = 0;
|
||||||
|
// Try loading as an RA .tem
|
||||||
|
reader = new BinaryReader( stream );
|
||||||
|
Width = reader.ReadUInt16();
|
||||||
|
Height = reader.ReadUInt16();
|
||||||
|
if( Width != 24 || Height != 24 )
|
||||||
|
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||||
|
|
||||||
|
/*NumTiles = */reader.ReadUInt16();
|
||||||
|
reader.ReadUInt16();
|
||||||
|
/*XDim = */reader.ReadUInt16();
|
||||||
|
/*YDim = */reader.ReadUInt16();
|
||||||
|
/*uint FileSize = */reader.ReadUInt32();
|
||||||
|
ImgStart = reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
IndexEnd = reader.ReadInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
IndexStart = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Write("IndexStart: {0}",IndexStart);
|
||||||
stream.Position = IndexStart;
|
stream.Position = IndexStart;
|
||||||
|
|
||||||
foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) )
|
foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) )
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
using( Stream s = FileSystem.Open( tilename + suffix ) )
|
using( Stream s = FileSystem.Open( tilename + suffix ) )
|
||||||
{
|
{
|
||||||
|
Log.Write(tilename+suffix);
|
||||||
if( !tiles.ContainsKey( (ushort)( start + i ) ) )
|
if( !tiles.ContainsKey( (ushort)( start + i ) ) )
|
||||||
tiles.Add( (ushort)( start + i ), new Terrain( s ) );
|
tiles.Add( (ushort)( start + i ), new Terrain( s ) );
|
||||||
}
|
}
|
||||||
@@ -88,9 +89,11 @@ namespace OpenRA.FileFormats
|
|||||||
public byte[] GetBytes(TileReference r)
|
public byte[] GetBytes(TileReference r)
|
||||||
{
|
{
|
||||||
Terrain tile;
|
Terrain tile;
|
||||||
if( tiles.TryGetValue( r.tile, out tile ) )
|
try {
|
||||||
return tile.TileBitmapBytes[ r.image ];
|
if( tiles.TryGetValue( r.tile, out tile ) )
|
||||||
|
return tile.TileBitmapBytes[ r.image ];
|
||||||
|
} catch (System.ArgumentOutOfRangeException) {}
|
||||||
|
|
||||||
byte[] missingTile = new byte[ 24 * 24 ];
|
byte[] missingTile = new byte[ 24 * 24 ];
|
||||||
for( int i = 0 ; i < missingTile.Length ; i++ )
|
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||||
missingTile[ i ] = 0x36;
|
missingTile[ i ] = 0x36;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
* This file is part of OpenRA.
|
* This file is part of OpenRA.
|
||||||
@@ -34,7 +34,9 @@ namespace OpenRA
|
|||||||
Sprite[] shadowBits = SpriteSheetBuilder.LoadAllSprites("shadow");
|
Sprite[] shadowBits = SpriteSheetBuilder.LoadAllSprites("shadow");
|
||||||
Sprite[,] sprites = new Sprite[128, 128];
|
Sprite[,] sprites = new Sprite[128, 128];
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
bool hasGPS = false;
|
|
||||||
|
// TODO: Testing
|
||||||
|
bool hasGPS = true;
|
||||||
Player owner;
|
Player owner;
|
||||||
Map map;
|
Map map;
|
||||||
public Rectangle? bounds;
|
public Rectangle? bounds;
|
||||||
|
|||||||
625
doc/cncff.txt
Normal file
625
doc/cncff.txt
Normal file
@@ -0,0 +1,625 @@
|
|||||||
|
COMMAND & CONQUER FILE FORMATS
|
||||||
|
|
||||||
|
Revision 4
|
||||||
|
|
||||||
|
by Vladan Bato (bat22@geocities.com)
|
||||||
|
|
||||||
|
This document explains the file formats used by Command & Conquer.
|
||||||
|
|
||||||
|
Command & Conquer is a tradmark of Westwood Studios, Inc.
|
||||||
|
Command & Conquer is Copyright (C)1995 Westwood Studios, Inc.
|
||||||
|
|
||||||
|
The information provided here is meant for programmers that want to make
|
||||||
|
editor and utilites for Command & Conquer. My explanation might not be
|
||||||
|
the best one, but it should be enough.
|
||||||
|
|
||||||
|
I can't guarantee that the information in here is correct. If you find any
|
||||||
|
errors, please report them to me.
|
||||||
|
|
||||||
|
In this document I'll use Pascal notation, and any code samples will be in
|
||||||
|
Pascal....
|
||||||
|
I wanted to rewrite them in C, but I don't have the time to test the code.
|
||||||
|
So, to avoid any risks, I'll use the code from Mix Manager.
|
||||||
|
|
||||||
|
In case you don't know, the information contained here has been used to
|
||||||
|
make the program Mix Manager, which contains a lot of conversion utilities
|
||||||
|
for the various formats. For more info, check my homepage (see the end of
|
||||||
|
the document).
|
||||||
|
|
||||||
|
===================
|
||||||
|
1. THE .MIX FILES
|
||||||
|
===================
|
||||||
|
|
||||||
|
You probably already know the format of these files, but I will add a
|
||||||
|
description here for completeness.
|
||||||
|
|
||||||
|
The MIX file consists of two parts :
|
||||||
|
-A header including the index of all the files contained within
|
||||||
|
-A body containing all the files
|
||||||
|
|
||||||
|
It's format is :
|
||||||
|
|
||||||
|
Header : record
|
||||||
|
NumFiles : word; {Number of files in MIX}
|
||||||
|
DataSize : longint; {Size of body}
|
||||||
|
Index : array [1..NumFiles] of
|
||||||
|
record
|
||||||
|
ID : longint; {File ID}
|
||||||
|
Start : longint; {Offset of file from the start of the
|
||||||
|
body}
|
||||||
|
Size : longint; {file size}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
The ID field is computed from the original filename, which is not stored in
|
||||||
|
the MIX.
|
||||||
|
The records are always sorted by the ID field (the numbers are signed
|
||||||
|
longints).
|
||||||
|
Note that the offsets are relative to the start of the body so to find the
|
||||||
|
actual offset in the MIX you have to add the size of the header which is
|
||||||
|
NumFiles*12+6
|
||||||
|
|
||||||
|
===================
|
||||||
|
2. THE .PAL FILES
|
||||||
|
===================
|
||||||
|
|
||||||
|
The most easiest files....
|
||||||
|
These files contain the palette in the same format used by VGA cards.
|
||||||
|
|
||||||
|
Palette : array [0..255] of record
|
||||||
|
red,green,blue:byte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Note that only the first 6 bits of each number are used, giving a total of
|
||||||
|
262144 possible colors (as opposed to the 8 bits used by .PCX files for
|
||||||
|
example).
|
||||||
|
|
||||||
|
=================================
|
||||||
|
3. THE TEMPLATE AND .BIN FILES
|
||||||
|
=================================
|
||||||
|
|
||||||
|
The Template files contain the map graphics, and can be found in the
|
||||||
|
theater specific MIX files (TEMPERAT.MIX, WINTER.MIX, DESERT.MIX).
|
||||||
|
The .BIN files contain the maps for the missions and are used in conjunction
|
||||||
|
with the .INI files.
|
||||||
|
|
||||||
|
I won't explain them here. They are explained with great detail in the
|
||||||
|
document titled "Command & Conquer maps" I wrote some time ago.
|
||||||
|
The said document can be found on my homepage.
|
||||||
|
|
||||||
|
===================
|
||||||
|
5. THE .SHP FILES
|
||||||
|
===================
|
||||||
|
|
||||||
|
The .SHP files contain almost all the graphics : units, structures,
|
||||||
|
trees,...
|
||||||
|
The header has the following structure :
|
||||||
|
|
||||||
|
Header : record
|
||||||
|
NumImages : word; {Number of images}
|
||||||
|
A,B : word; {Unknown}
|
||||||
|
Width,
|
||||||
|
Height : word; {Width and Height of the images}
|
||||||
|
C : longint; {Unknown}
|
||||||
|
end;
|
||||||
|
|
||||||
|
If you know something about those unknown fields, please e-mail me.
|
||||||
|
Following that there's an array of records, one for each image :
|
||||||
|
|
||||||
|
Offsets : array [0..NumImages+1] of
|
||||||
|
record
|
||||||
|
Offset : longint; {Offset and format of image in file}
|
||||||
|
RefOffs : longint; {Offset and format of image on
|
||||||
|
which it is based}
|
||||||
|
end;
|
||||||
|
|
||||||
|
The most significant byte (last) of the Offset and RefOffs fields
|
||||||
|
contains the format, while the lower three are used for the offset.
|
||||||
|
The format byte can have one of the three values : 80h, 40h, 20h.
|
||||||
|
I will call the three image formats Format80, Format40 and Format20.
|
||||||
|
|
||||||
|
The Format80 images are compressed with a compression method I'll explain
|
||||||
|
later.
|
||||||
|
|
||||||
|
The Format40 images must be xor-ed with a Format80 image. That's what the
|
||||||
|
RefOffs field is used for. It tells which Format80 image they are
|
||||||
|
based upon. The Format40 will be explained in detail later.
|
||||||
|
|
||||||
|
The Format20 images use the same format as the Format40, the difference is
|
||||||
|
that they are xor-ed with the image that precedes them in the file. That can
|
||||||
|
be either in Format20 or in Format40.
|
||||||
|
The offset part of the RefOffs field contains the number of the first
|
||||||
|
Format40 image in the chain, and the format field is always 48h.
|
||||||
|
|
||||||
|
Here's an example :
|
||||||
|
|
||||||
|
0) Off0(three bytes) 80h 000000h 00h
|
||||||
|
1) Off1(three bytes) 80h 000000h 00h
|
||||||
|
2) Off2(three bytes) 40h Off1 80h
|
||||||
|
3) Off3(three bytes) 80h 000000h 00h
|
||||||
|
4) Off4(three bytes) 40h Off1 80h
|
||||||
|
5) Off5(three bytes) 20h 000400h 48h
|
||||||
|
6) Off6(three bytes) 20h 000400h 48h
|
||||||
|
7) Off7(three bytes) 40h Off3 80h
|
||||||
|
|
||||||
|
For example to draw image 7, you have to draw the image 3 first (whose
|
||||||
|
offset
|
||||||
|
and format are given) and then xor image 7 over it.
|
||||||
|
|
||||||
|
To draw image 6, you have to xor it over the previous image, i.e. 5, which
|
||||||
|
is format20 again, that means that it has to be xor-ed over image 4, which
|
||||||
|
is in format40, i.e. it must be xor-ed over the image in format80 it has a
|
||||||
|
reference to. In this case it's image 1. Thus the chain is 1,4,5,6.
|
||||||
|
This is one way to see it, the other could be :
|
||||||
|
Image 6 is in Format20, the RefOffs field contains the number of the first
|
||||||
|
Format40 image in the chain, in this case image 4. To draw Image 4, the
|
||||||
|
Image 1 has to be drawn first, next is image 4, and then all the images
|
||||||
|
from the 4th to the 6th have to be xor-ed over the previous.
|
||||||
|
|
||||||
|
I made some experiments and found out that you don't have to use the
|
||||||
|
Format40 and Format20 images. I tried converting all of them into Format80
|
||||||
|
and it worked.
|
||||||
|
|
||||||
|
Also, when changing graphics, note that all the unit and structure graphics
|
||||||
|
should be drawn using the GDI colors, which will be automatically converted
|
||||||
|
for the other sides.
|
||||||
|
The palette you should use is one of those found in DESERT.MIX, WINTER.MIX
|
||||||
|
and TEMPERAT.MIX. The GDI colors are colors 0B0h-0BFh. The other colors
|
||||||
|
won't be converted and will remain the same for all the sides (be sure to
|
||||||
|
use only the colors that are the same all three palettes).
|
||||||
|
|
||||||
|
The above applies only to the graphics that appear in all three theaters
|
||||||
|
(the .SHP file found in CONQUER.MIX). The graphics for the structures and
|
||||||
|
overlays that appear in a single theater (found inside the theater specific
|
||||||
|
MIX) can use the palette entries that are unique for that theater (and will
|
||||||
|
be shown with garbled colors in the others).
|
||||||
|
|
||||||
|
Also a special color is used for shadows. It's color 04h. In the palettes
|
||||||
|
it's bright green, but C&C puts a shadow instead of it. I don't know how
|
||||||
|
the shadows are calculated however.
|
||||||
|
|
||||||
|
You should've noticed that the array has NumImages+2 elements when only
|
||||||
|
NumImages elements are needed. The last one contains zeros, and the one
|
||||||
|
before
|
||||||
|
that points to the end of the file. These two can be used to identify the
|
||||||
|
file as a .SHP.
|
||||||
|
|
||||||
|
Here's the description of the compression formats : Format80 and Format40.
|
||||||
|
|
||||||
|
----------
|
||||||
|
Format80
|
||||||
|
----------
|
||||||
|
|
||||||
|
There are several different commands, with different sizes : form 1 to 5
|
||||||
|
bytes.
|
||||||
|
The positions mentioned below always refer to the destination buffer (i.e.
|
||||||
|
the uncompressed image). The relative positions are relative to the current
|
||||||
|
position in the destination buffer, which is one byte beyond the last
|
||||||
|
written
|
||||||
|
byte.
|
||||||
|
|
||||||
|
I will give some sample code at the end.
|
||||||
|
|
||||||
|
(1) 1 byte
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 1 | 0 | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
\_______________________/
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
This one means : copy next Count bytes as is from Source to Dest.
|
||||||
|
|
||||||
|
(2) 2 bytes
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
|
||||||
|
| 0 | | | | | | | | | | | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
|
||||||
|
\___________/\__________________________________________________/
|
||||||
|
| |
|
||||||
|
Count-3 Relative Pos.
|
||||||
|
|
||||||
|
This means copy Count bytes from Dest at Current Pos.-Rel. Pos. to
|
||||||
|
Current position.
|
||||||
|
Note that you have to add 3 to the number you find in the bits 4-6 of the
|
||||||
|
first byte to obtain the Count.
|
||||||
|
Note that if the Rel. Pos. is 1, that means repeat Count times the
|
||||||
|
previous
|
||||||
|
byte.
|
||||||
|
|
||||||
|
(3) 3 bytes
|
||||||
|
+---+---+---+---+---+---+---+---+ +---------------+---------------+
|
||||||
|
| 1 | 1 | | | | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +---------------+---------------+
|
||||||
|
\_______________________/ Pos
|
||||||
|
|
|
||||||
|
Count-3
|
||||||
|
|
||||||
|
Copy Count bytes from Pos, where Pos is absolute from the start of the
|
||||||
|
destination buffer. (Pos is a word, that means that the images can't be
|
||||||
|
larger than 64K)
|
||||||
|
|
||||||
|
(4) 4 bytes
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+-------+ +-------+
|
||||||
|
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+-------+ +-------+
|
||||||
|
Count Color
|
||||||
|
|
||||||
|
Write Color Count times.
|
||||||
|
(Count is a word, color is a byte)
|
||||||
|
|
||||||
|
(5) 5 bytes
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+-------+ +-------+-------+
|
||||||
|
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+-------+ +-------+-------+
|
||||||
|
Count Pos
|
||||||
|
|
||||||
|
Copy Count bytes from Dest. starting at Pos. Pos is absolute from the
|
||||||
|
start of the Destination buffer.
|
||||||
|
Both Count and Pos are words.
|
||||||
|
|
||||||
|
These are all the commands I found out. Maybe there are other ones, but I
|
||||||
|
haven't seen them yet.
|
||||||
|
|
||||||
|
All the images end with a 80h command.
|
||||||
|
|
||||||
|
To make things more clearer here's a piece of code that will uncompress the
|
||||||
|
image.
|
||||||
|
|
||||||
|
DP = destination pointer
|
||||||
|
SP = source pointer
|
||||||
|
Source and Dest are the two buffers
|
||||||
|
|
||||||
|
|
||||||
|
SP:=0;
|
||||||
|
DP:=0;
|
||||||
|
repeat
|
||||||
|
Com:=Source[SP];
|
||||||
|
inc(SP);
|
||||||
|
b7:=Com shr 7; {b7 is bit 7 of Com}
|
||||||
|
case b7 of
|
||||||
|
0 : begin {copy command (2)}
|
||||||
|
{Count is bits 4-6 + 3}
|
||||||
|
Count:=(Com and $7F) shr 4 + 3;
|
||||||
|
{Position is bits 0-3, with bits 0-7 of next byte}
|
||||||
|
Posit:=(Com and $0F) shl 8+Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
{Starting pos=Cur pos. - calculated value}
|
||||||
|
Posit:=DP-Posit;
|
||||||
|
for i:=Posit to Posit+Count-1 do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[i];
|
||||||
|
Inc(DP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
1 : begin
|
||||||
|
{Check bit 6 of Com}
|
||||||
|
b6:=(Com and $40) shr 6;
|
||||||
|
case b6 of
|
||||||
|
0 : begin {Copy as is command (1)}
|
||||||
|
Count:=Com and $3F; {mask 2 topmost bits}
|
||||||
|
if Count=0 then break; {EOF marker}
|
||||||
|
for i:=1 to Count do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Source[SP];
|
||||||
|
Inc(DP);
|
||||||
|
Inc(SP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
1 : begin {large copy, very large copy and fill commands}
|
||||||
|
{Count = (bits 0-5 of Com) +3}
|
||||||
|
{if Com=FEh then fill, if Com=FFh then very large copy}
|
||||||
|
Count:=Com and $3F;
|
||||||
|
if Count<$3E then {large copy (3)}
|
||||||
|
begin
|
||||||
|
Inc(Count,3);
|
||||||
|
{Next word = pos. from start of image}
|
||||||
|
Posit:=Word(Source[SP]);
|
||||||
|
Inc(SP,2);
|
||||||
|
for i:=Posit to Posit+Count-1 do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[i];
|
||||||
|
Inc(DP);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if Count=$3F then {very large copy (5)}
|
||||||
|
begin
|
||||||
|
{next 2 words are Count and Pos}
|
||||||
|
Count:=Word(Source[SP]);
|
||||||
|
Posit:=Word(Source[SP+2]);
|
||||||
|
Inc(SP,4);
|
||||||
|
for i:=Posit to Posit+Count-1 do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[i];
|
||||||
|
Inc(DP);
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
begin {Count=$3E, fill (4)}
|
||||||
|
{Next word is count, the byte after is color}
|
||||||
|
Count:=Word(Source[SP]);
|
||||||
|
Inc(SP,2);
|
||||||
|
b:=Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
for i:=0 to Count-1 do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=b;
|
||||||
|
inc(DP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
|
||||||
|
Note that you won't be able to compile this code, because the typecasting
|
||||||
|
won't work. (But I'm sure you'll be able to fix it).
|
||||||
|
|
||||||
|
|
||||||
|
----------
|
||||||
|
Format40
|
||||||
|
----------
|
||||||
|
|
||||||
|
As I said before the images in Format40 must be xor-ed over a previous
|
||||||
|
image, or against a black screen (as in the .WSA format).
|
||||||
|
It is used when there are only minor changes between an image and a
|
||||||
|
following one.
|
||||||
|
|
||||||
|
Here I'll assume that the old image is in Dest, and that the Dest pointer is
|
||||||
|
set to the beginning of that buffer.
|
||||||
|
|
||||||
|
As for the Format80, there are many commands :
|
||||||
|
|
||||||
|
|
||||||
|
(1) 1 byte
|
||||||
|
byte
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 1 | | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
\___________________________/
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
Skip count bytes in Dest (move the pointer forward).
|
||||||
|
|
||||||
|
(2) 3 bytes
|
||||||
|
byte word
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+-----+-------+
|
||||||
|
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | ... | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+-----+-------+
|
||||||
|
\_____________/
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
Skip count bytes.
|
||||||
|
|
||||||
|
(3) 3 bytes
|
||||||
|
byte word
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+-----+-------+
|
||||||
|
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 0 | ... | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+-----+-------+
|
||||||
|
\_____________/
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
Xor next count bytes. That means xor count bytes from Source with bytes
|
||||||
|
in Dest.
|
||||||
|
|
||||||
|
(4) 4 bytes
|
||||||
|
byte word byte
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+-----+-------+ +-------+
|
||||||
|
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | ... | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +---+---+-----+-------+ +-------+
|
||||||
|
\_____________/ value
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
Xor next count bytes in Dest with value.
|
||||||
|
|
||||||
|
5) 1 byte
|
||||||
|
byte
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 0 | | | | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
\___________________________/
|
||||||
|
|
|
||||||
|
Count
|
||||||
|
|
||||||
|
Xor next count bytes from source with dest.
|
||||||
|
|
||||||
|
6) 3 bytes
|
||||||
|
byte byte byte
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+ +-------+
|
||||||
|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | |
|
||||||
|
+---+---+---+---+---+---+---+---+ +-------+ +-------+
|
||||||
|
Count Value
|
||||||
|
|
||||||
|
Xor next count bytes with value.
|
||||||
|
|
||||||
|
|
||||||
|
All images end with a 80h 00h 00h command.
|
||||||
|
|
||||||
|
I think these are all the commands, but there might be some other.
|
||||||
|
If you find anything new, please e-mail me.
|
||||||
|
|
||||||
|
As before here's some code :
|
||||||
|
|
||||||
|
DP = destination pointer
|
||||||
|
SP = source pointer
|
||||||
|
Source is buffer containing the Format40 data
|
||||||
|
Dest is the buffer containing the image over which the second has
|
||||||
|
to be xor-ed
|
||||||
|
|
||||||
|
|
||||||
|
SP:=0;
|
||||||
|
DP:=0;
|
||||||
|
repeat
|
||||||
|
Com:=Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
|
||||||
|
if (Com and $80)<>0 then {if bit 7 set}
|
||||||
|
begin
|
||||||
|
if Com<>$80 then {small skip command (1)}
|
||||||
|
begin
|
||||||
|
Count:=Com and $7F;
|
||||||
|
Inc(DP,Count);
|
||||||
|
end
|
||||||
|
else {Big commands}
|
||||||
|
begin
|
||||||
|
Count:=Word(Source[SP]);
|
||||||
|
if Count=0 then break;
|
||||||
|
Inc(SP,2);
|
||||||
|
|
||||||
|
Tc:=(Count and $C000) shr 14; {Tc=two topmost bits of count}
|
||||||
|
|
||||||
|
case Tc of
|
||||||
|
0,1 : begin {Big skip (2)}
|
||||||
|
Inc(DP,Count);
|
||||||
|
end;
|
||||||
|
2 : begin {big xor (3)}
|
||||||
|
Count:=Count and $3FFF;
|
||||||
|
for i:=1 to Count do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[DP] xor Source[SP];
|
||||||
|
Inc(DP);
|
||||||
|
Inc(SP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
3 : begin {big repeated xor (4)}
|
||||||
|
Count:=Count and $3FFF;
|
||||||
|
b:=Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
for i:=1 to Count do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[DP] xor b;
|
||||||
|
Inc(DP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else {xor command}
|
||||||
|
begin
|
||||||
|
Count:=Com;
|
||||||
|
if Count=0 then
|
||||||
|
begin {repeated xor (6)}
|
||||||
|
Count:=Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
b:=Source[SP];
|
||||||
|
Inc(SP);
|
||||||
|
for i:=1 to Count do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[DP] xor b;
|
||||||
|
Inc(DP);
|
||||||
|
end;
|
||||||
|
end else {copy xor (5)}
|
||||||
|
for i:=1 to Count do
|
||||||
|
begin
|
||||||
|
Dest[DP]:=Dest[DP] xor Source[SP];
|
||||||
|
Inc(DP);
|
||||||
|
Inc(SP);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
===================
|
||||||
|
6. THE .CPS FILES
|
||||||
|
===================
|
||||||
|
|
||||||
|
The .CPS files contain 320x200x256 images. The images are compressed with
|
||||||
|
the Format80 compression method. They may or may not contain a palette.
|
||||||
|
|
||||||
|
The header has the following structure :
|
||||||
|
|
||||||
|
Header : record
|
||||||
|
Size : word; {File size - 2}
|
||||||
|
Unknown : word; {Always 0004h}
|
||||||
|
ImSize : word; {Size of uncompressed image (always 0FA00h)}
|
||||||
|
Palette : longint; {Is there a palette ?}
|
||||||
|
end;
|
||||||
|
|
||||||
|
If Palette is 03000000h then there's a palette after the header, otherwise
|
||||||
|
the image follows. CPS file without palette can be found in the SETUP.MIX
|
||||||
|
file, and they all use the Palette that can be found inside the same .MIX.
|
||||||
|
|
||||||
|
The image that follows the palette (or the Header) is in Format80 which is
|
||||||
|
explained above.
|
||||||
|
|
||||||
|
===================
|
||||||
|
7. THE .WSA FILES
|
||||||
|
===================
|
||||||
|
|
||||||
|
|
||||||
|
WSA files contain short animations and can be found in the GENERAL.MIX
|
||||||
|
files.
|
||||||
|
They are basically a series of Format40 images, that are then compressed
|
||||||
|
with
|
||||||
|
Format80.
|
||||||
|
|
||||||
|
The header is :
|
||||||
|
|
||||||
|
Header : record
|
||||||
|
NumFrames : word; {Number of frames}
|
||||||
|
X,Y : word; {Position on screen of the upper left
|
||||||
|
corner}
|
||||||
|
W,H : word; {Width and height of the images}
|
||||||
|
Delta : longint; {Frames/Sec = Delta/(2^10)}
|
||||||
|
end;
|
||||||
|
|
||||||
|
Following that there's an array of offsets :
|
||||||
|
|
||||||
|
Offsets : array [0..NumFrames+1] of longint;
|
||||||
|
|
||||||
|
The obtain the actual offset, you have to add 300h. That is the size of the
|
||||||
|
palette that follows the Offsets array.
|
||||||
|
As for .SHP files the two last offsets have a special meaning.
|
||||||
|
If the last offset is 0 then the one before it points to the end of file
|
||||||
|
(after you added 300h of course).
|
||||||
|
If the last one is <>0 then it points to the end of the file, and the
|
||||||
|
one before it points to a special frame that gives you the difference
|
||||||
|
between the last and the first frame. This is used when you have to loop the
|
||||||
|
animation.
|
||||||
|
|
||||||
|
As I said before, the images are in Format40 but are then compressed with
|
||||||
|
Format80. That means that you first have to uncompress the Format80 and then
|
||||||
|
decode the Format40 image you obtain.
|
||||||
|
The first frame should be xor-ed over a black image (filled with zeros), all
|
||||||
|
the other are xor-ed over the previous one.
|
||||||
|
|
||||||
|
There is a variant of the file without the palette that can be found in
|
||||||
|
SETUP.MIX but I wasn't able to decode it (maybe there are some commands I
|
||||||
|
don't know about)...
|
||||||
|
|
||||||
|
=====================
|
||||||
|
8. ADDITIONAL NOTES
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The VQA files (that contain movies) have been decoded by Aaron Glover
|
||||||
|
(arn@ibm.net), and are explained in a document he wrote up.
|
||||||
|
You can find the document on my homepage (or ask him directly).
|
||||||
|
|
||||||
|
What is still missing are the .AUD files.
|
||||||
|
It seems that the AUD files use some kind of lossy sound compression,
|
||||||
|
which means that it is almost impossible to decode them.
|
||||||
|
However if someone manages to work them out, I'd really appreciate some
|
||||||
|
info.
|
||||||
|
|
||||||
|
I know my explanations are not very good, but you'll have to bear them,
|
||||||
|
unless someone else wants to rewrite this.
|
||||||
|
|
||||||
|
============
|
||||||
|
9. CREDITS
|
||||||
|
============
|
||||||
|
|
||||||
|
I wish to thank the following people :
|
||||||
|
|
||||||
|
-Andrew Griffin (buggy@adam.com.au) for starting it all.
|
||||||
|
-Aaron Glover (arn@ibm.net) and
|
||||||
|
Denis Moeller (d.moeller@rendsburg.netsurf.de) for their work on .SHP
|
||||||
|
files.
|
||||||
|
-Aaron Glover for decoding the VQA files.
|
||||||
|
-Carl Kenner (andrew.kenner@unisa.edu.au) for the info on .CPS files.
|
||||||
|
|
||||||
|
|
||||||
|
Vladan Bato (bat22@geocities.com)
|
||||||
|
http://www.geocities.com/SiliconValley/8682
|
||||||
500
doc/cncmap.txt
Normal file
500
doc/cncmap.txt
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
THE COMMAND & CONQUER MAPS
|
||||||
|
|
||||||
|
Rev. 1f
|
||||||
|
|
||||||
|
by Vladan Bato (bat22@geocities.com)
|
||||||
|
|
||||||
|
This document explains the format of the maps and the associated graphics
|
||||||
|
files. It has also a complete listing of all available map values.
|
||||||
|
This document is meant for people who want to make a C&C scenery editor.
|
||||||
|
You can also use it to edit manually the maps but IMHO it's a suicide if you
|
||||||
|
can't see what you are doing.
|
||||||
|
|
||||||
|
ABOUT .MIX FILES
|
||||||
|
|
||||||
|
First of all I will explain the structure of MIX files, since all the
|
||||||
|
graphics are in the TEMPERAT, DESERT, and WINTER.MIX files.
|
||||||
|
|
||||||
|
Each MIX file contains several internal files that can be extracted. I will
|
||||||
|
refer to the internal files as just "files".
|
||||||
|
The MIX file is made up of two parts: the first one is the Header, the
|
||||||
|
second one is the Body that contains all the files.
|
||||||
|
|
||||||
|
The structure of the header is:
|
||||||
|
(I will use pascal notation here)
|
||||||
|
|
||||||
|
Header = record
|
||||||
|
NumFiles : word; {Number of internal files}
|
||||||
|
BodyLength : longint; {Length of the body}
|
||||||
|
Index : array [1..NumFiles] of
|
||||||
|
record
|
||||||
|
ID : longint; {ID of file, computed from filename}
|
||||||
|
Start : longint; {Offset of file in the body}
|
||||||
|
Size : longint; {Size of the file}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Of course you can't use directly such a structure in pascal because its
|
||||||
|
length is not fixed.
|
||||||
|
Note that the offsets are relative to the start of the body so to find the
|
||||||
|
actual offset in the MIX you have to add the size of the header which is
|
||||||
|
NumFiles*12+6
|
||||||
|
|
||||||
|
Note also that the records in the Index are not in the same order as the
|
||||||
|
files are physically stored in the MIX. In this document I will always refer
|
||||||
|
to the record number in the index and not to the file's actual position in
|
||||||
|
the MIX.
|
||||||
|
|
||||||
|
ABOUT THE MAP
|
||||||
|
|
||||||
|
All the maps are 64x64 squares large. There are 2 bytes of information for
|
||||||
|
each square, thus the file is 8192 bytes long.
|
||||||
|
|
||||||
|
The two bytes indicate which image should be placed there. The first one
|
||||||
|
indicates in which of the internal files of TEMPERAT, DESERT or WINTER.MIX
|
||||||
|
it is. Each of these internal files contains several images; the second byte
|
||||||
|
tells which of those images should be taken. The images inside one of the
|
||||||
|
internal files, if put together, form a larger image. It can be a bridge,
|
||||||
|
a road section, etc. These are called "templates". Thus, each internal file
|
||||||
|
contains a template. Each template is made of several "tiles" (images).
|
||||||
|
Each square of the map contains one tile. It's not necessary to put all
|
||||||
|
the tiles of a template on the map.
|
||||||
|
|
||||||
|
There are templates of various sizes: from 1x1 to 6x8.
|
||||||
|
(I will always write the dimensions as WidthxHeight)
|
||||||
|
The tile numbers range from 0 to WxH-1.
|
||||||
|
However there are some tiles, which I call "empty tiles", that don't have
|
||||||
|
any images associated with them. If you try using them C&C will display
|
||||||
|
the default terrain for that Theater instead. There are empty tiles
|
||||||
|
especially in the corners of large templates.
|
||||||
|
|
||||||
|
An example may be useful:
|
||||||
|
|
||||||
|
The SW-NE bridge in the temperate theater has two empty tiles:
|
||||||
|
XXOr X - Empty tile O - other tiles
|
||||||
|
wbbO b - Bridge
|
||||||
|
Obbw w - Water (This is probably wrong, I can't check now)
|
||||||
|
rOOO r - road
|
||||||
|
|
||||||
|
We can see that in the upper left corner there are two empty tiles.
|
||||||
|
We can put the values 00 and 01 in our map (as the second byte; the first
|
||||||
|
would be A5h for the bridge), in that case we'll see some grass there. But
|
||||||
|
we can replace those two tiles with anything else without disturbing the
|
||||||
|
rest. What I mean, is that if we changed any other tile, a piece of river
|
||||||
|
would be missing or a rock could be cut, ruining the map; but if we
|
||||||
|
replace the empty tiles everything is OK.
|
||||||
|
|
||||||
|
So, when we have an empty tile, we can leave it there, or replace it with
|
||||||
|
anything else. There are two exceptions to this rule however:
|
||||||
|
|
||||||
|
1) Sometimes the empty tiles should be water, but if we don't replace them
|
||||||
|
C&C will show land in the middle of our lake or sea;
|
||||||
|
2) There are templates containing roads that finish in one of the corners,
|
||||||
|
so that the next template must have an empty tile in the opposite corner
|
||||||
|
to stick to the other.
|
||||||
|
|
||||||
|
An example might help:
|
||||||
|
|
||||||
|
Imagine that we have two road sections like these:
|
||||||
|
OOrr OOrr
|
||||||
|
Orrr Orrr
|
||||||
|
rrrO rrrO
|
||||||
|
rrOO rrOO
|
||||||
|
|
||||||
|
and we want to stick them diagonally:
|
||||||
|
OOrr
|
||||||
|
Orrr
|
||||||
|
rrrO
|
||||||
|
rrOO
|
||||||
|
OOrr
|
||||||
|
Orrr
|
||||||
|
rrrO
|
||||||
|
rrOO
|
||||||
|
|
||||||
|
Something is obviously missing. We need to add some tiles to fill it like
|
||||||
|
this:
|
||||||
|
OOrr
|
||||||
|
Orrr
|
||||||
|
rrrO
|
||||||
|
RrrOO
|
||||||
|
OOrrR
|
||||||
|
Orrr
|
||||||
|
rrrO
|
||||||
|
rrOO
|
||||||
|
|
||||||
|
The solution could be to have two templates like these:
|
||||||
|
OOOO ROOO
|
||||||
|
OOOO OOOO
|
||||||
|
OOOO OOOO
|
||||||
|
OOOR OOOO
|
||||||
|
or to have one little template with empty tiles:
|
||||||
|
RX
|
||||||
|
XR (Where X are empty tiles)
|
||||||
|
|
||||||
|
Now we can put this between the two road sections, replacing the empty
|
||||||
|
tiles with the corner tiles of the road sections.
|
||||||
|
|
||||||
|
There are many road sections like this and I've indicated them with
|
||||||
|
"(Conn.)" in the table at the end of this document.
|
||||||
|
|
||||||
|
ABOUT THE DESERT, TEMPERAT, and WINTER.MIX FILES
|
||||||
|
|
||||||
|
These are the files that hold the graphics for the templates. There's one
|
||||||
|
file inside the MIX for each template, and each file has several tiles
|
||||||
|
inside.
|
||||||
|
There are other files inside the MIXes, probably for the trees and other
|
||||||
|
overlay elements but I don't know the format. If somebody knows their
|
||||||
|
format, please let me know.
|
||||||
|
|
||||||
|
In each MIX there's also a palette, the entries are:
|
||||||
|
DESERT.MIX entry n. 26
|
||||||
|
TEMPERAT.MIX entry n. 62
|
||||||
|
WINTER.MIX entry n. 62
|
||||||
|
|
||||||
|
I will now explain the format of the files with map graphics.
|
||||||
|
First of all there's a header with the following structure:
|
||||||
|
|
||||||
|
Header = record
|
||||||
|
Width : word; {Width of images, always 24 (18h)}
|
||||||
|
Heigth : word; {Heigth of images, always 24}
|
||||||
|
NumTil : word; {Number of Tiles (may differ from num. of Images}
|
||||||
|
Zero1 : word; {Seems to be always 0000h}
|
||||||
|
Size : longint; {size of file}
|
||||||
|
ImgStart : longint; {Offset of first image}
|
||||||
|
Zero2 : longint; {Seems to be always 00000000h}
|
||||||
|
ID1 : word; {Always FFFFh}
|
||||||
|
ID2 : word; {Always 1A0Dh (or 0D1Ah I can't remeber}
|
||||||
|
Index2 : longint; {Offset of Index2}
|
||||||
|
Index1 : longint; {Offset of Index1} {I will explain these
|
||||||
|
later}
|
||||||
|
end;
|
||||||
|
|
||||||
|
The images follow the header but I suppose they could be anywhere.
|
||||||
|
They are all 24x24 pixel, uncompressed and are one after the other.
|
||||||
|
Note that the number of images may differ from the number of tiles if
|
||||||
|
there are some empty tiles. If there are empty tiles, the actual number of
|
||||||
|
images can be smaller than the number of tiles. To work out the number
|
||||||
|
of images you can use the formula : (Index1-ImgStart)/(24*24).
|
||||||
|
However, you won't have to do this if the index is not corrupt.
|
||||||
|
|
||||||
|
Index1 has the following format:
|
||||||
|
|
||||||
|
Index1 : array [0..NumTil-1] of byte;
|
||||||
|
|
||||||
|
where NumTil is the number of tiles.
|
||||||
|
|
||||||
|
Each entry in Index1 corresponds to one tile, and indicates which image
|
||||||
|
(of that file) is associated with it. If the entry is FFh than that tile
|
||||||
|
is empty.
|
||||||
|
|
||||||
|
Index2 is an array of NumImages bytes where NumImages is the real
|
||||||
|
number of images in the file. However it's always filled with zeros
|
||||||
|
(sometimes there's a 1 somewhere but I don't know it's meaning).
|
||||||
|
|
||||||
|
Note that there's no way to know the dimensions (Width and Height) of the
|
||||||
|
template. If there are 6 tiles it could be 6x1, 1x6, 3x2, 2x3. I worked out
|
||||||
|
the dimensions of all templates myself (It's easy, all you have to do is to
|
||||||
|
try different widths and look at the screen).
|
||||||
|
|
||||||
|
|
||||||
|
For example a procedure that has to display template 61h, tile 3 of the
|
||||||
|
Desert theater would do:
|
||||||
|
1) Look in the table and find in which file it is in (entry 168 of
|
||||||
|
DESERT.MIX)
|
||||||
|
2) Open that file (seek it inside the MIX)
|
||||||
|
3) Read the Header
|
||||||
|
4) Read Index1 and read the 4th byte (for tile 3), let it be N
|
||||||
|
5) Seek ImgStart+Width*Height*N
|
||||||
|
6) Read the Image and display it
|
||||||
|
|
||||||
|
AND FINALLY THE TABLE
|
||||||
|
|
||||||
|
Here is the table of all available map values (template numbers), the
|
||||||
|
dimensions and the relative entries in the DESERT, WINTER, and TEMPERAT.MIX.
|
||||||
|
There's also a brief description for those that don't want or don't know
|
||||||
|
how to write an editor. However, I think that it will be difficult to stick
|
||||||
|
the templates together without seeing them.
|
||||||
|
|
||||||
|
An "x" means that the template doesn't exist in that theater. There are many
|
||||||
|
templates that exist only in one theater and will show as black holes in the
|
||||||
|
others (causing the HOM effect). The WINTER and TEMPERATE theaters are
|
||||||
|
however very similar, and differ only in a few templates.
|
||||||
|
The roads and cliffs are mostly the same for the three theaters, but be
|
||||||
|
careful about the river and coast templates because they are not the same.
|
||||||
|
|
||||||
|
V | DES | TEM | WIN | Dim. | Name | Description
|
||||||
|
-----+-----+-----+-----+-------+----------+---------------------------------
|
||||||
|
--
|
||||||
|
00h | 007 | 011 | 028 | [4x4] | CLEAR1 | Default terrain
|
||||||
|
01h | 002 | 007 | 007 | [1x1] | W1 | Water (not animated)
|
||||||
|
02h | x | 009 | 009 | [2x2] | W2 | Water
|
||||||
|
03h | x | 087 | 087 | [3x3] | SH1 | Coast WD (1)
|
||||||
|
04h | x | 106 | 105 | [3x3] | SH2 | Coast WD
|
||||||
|
05h | x | 126 | 124 | [1x1] | SH3 | Rock in water
|
||||||
|
06h | x | 143 | 140 | [2x1] | SH4 | Rock in water
|
||||||
|
07h | x | 159 | 157 | [3x3] | SH5 | Coast WD
|
||||||
|
08h | x | 018 | 017 | [3x3] | SH11 | Fjord WD
|
||||||
|
09h | x | 024 | 023 | [3x3] | SH12 | Coast WU
|
||||||
|
0Ah | x | 031 | 031 | [3x3] | SH13 | Coast WU
|
||||||
|
0Bh | x | 037 | 037 | [3x3] | SH14 | Coast WU
|
||||||
|
0Ch | x | 042 | 042 | [3x3] | SH15 | Coast WU
|
||||||
|
0Dh | 106 | 074 | 074 | [2x2] | S01 | Cliff Left Edge
|
||||||
|
0Eh | 122 | 093 | 092 | [2x3] | S02 | Cliff Wu-Wd (2)
|
||||||
|
0Fh | 138 | 112 | 110 | [2x2] | S03 | Cliff W-E
|
||||||
|
10h | 154 | 131 | 128 | [2x2] | S04 | Cliff W-E
|
||||||
|
11h | 170 | 147 | 144 | [2x2] | S05 | Cliff W-E
|
||||||
|
12h | 185 | 163 | 161 | [2x3] | S06 | Cliff Wd-Eu
|
||||||
|
13h | 200 | 180 | 179 | [2x2] | S07 | Cliff Right Edge
|
||||||
|
14h | 212 | 195 | 195 | [2x2] | S08 | Cliff Top Edge
|
||||||
|
15h | 225 | 208 | 209 | [3x2] | S09 | Cliff N-S
|
||||||
|
16h | 096 | 064 | 064 | [2x2] | S10 | Cliff N-S
|
||||||
|
17h | 108 | 078 | 078 | [2x2] | S11 | Cliff N-S
|
||||||
|
18h | 124 | 097 | 096 | [2x2] | S12 | Cliff N-S
|
||||||
|
19h | 140 | 117 | 115 | [3x2] | S13 | Cliff N-S
|
||||||
|
1Ah | 157 | 135 | 132 | [2x2] | S14 | Cliff Bottom Edge
|
||||||
|
1Bh | 172 | 151 | 149 | [2x2] | S15 | Cliff Left Edge
|
||||||
|
1Ch | 187 | 167 | 166 | [2x3] | S16 | Cliff Wu-Ed
|
||||||
|
1Dh | 202 | 184 | 184 | [2x2] | S17 | Cliff W-E
|
||||||
|
1Eh | 215 | 199 | 200 | [2x2] | S18 | Cliff W-E
|
||||||
|
1Fh | 228 | 211 | 213 | [2x2] | S19 | Cliff W-E
|
||||||
|
20h | 098 | 068 | 069 | [2x3] | S20 | Cliff Wu-Ed
|
||||||
|
21h | 110 | 082 | 082 | [1x2] | S21 | Cliff Right Edge
|
||||||
|
22h | 126 | 101 | 100 | [2x1] | S22 | Cliff Corner S-E Internal
|
||||||
|
23h | 142 | 121 | 119 | [3x2] | S23 | Cliff Sl-Nr
|
||||||
|
24h | 159 | 139 | 136 | [2x2] | S24 | Cliff N-S
|
||||||
|
25h | 174 | 155 | 153 | [2x2] | S25 | Cliff N-S
|
||||||
|
26h | 189 | 171 | 170 | [2x2] | S26 | Cliff N-S
|
||||||
|
27h | 204 | 188 | 188 | [3x2] | S27 | Cliff Nl-Sr
|
||||||
|
28h | 218 | 202 | 203 | [2x2] | S28 | Cliff Bottom Edge
|
||||||
|
29h | 230 | 213 | 215 | [2x2] | S29 | Cliff Corner N-E External
|
||||||
|
2Ah | 101 | 070 | 071 | [2x2] | S30 | Cliff Corner S-E Ext
|
||||||
|
2Bh | 113 | 084 | 084 | [2x2] | S31 | Cliff Corner W-S Ext
|
||||||
|
2Ch | 129 | 103 | 102 | [2x2] | S32 | Cliff Corner N-W Ext
|
||||||
|
2Dh | 145 | 123 | 121 | [2x2] | S33 | Cliff Corner N-E Internal
|
||||||
|
2Eh | 162 | 141 | 138 | [2x2] | S34 | Cliff Corner S-E Int
|
||||||
|
2Fh | 177 | 157 | 155 | [2x2] | S35 | Cliff Corner W-S Int
|
||||||
|
30h | 192 | 173 | 172 | [2x2] | S36 | Cliff Corner W-N Int
|
||||||
|
31h | 207 | 190 | 190 | [2x2] | S37 | Cliff Junction NW-SE
|
||||||
|
32h | 221 | 204 | 205 | [2x2] | S38 | Cliff Junction SW-NE
|
||||||
|
33h | x | 027 | 026 | [3x3] | SH32 | Coast Corner N-W Int
|
||||||
|
34h | x | 033 | 033 | [3x3] | SH33 | Coast Corner N-E Int
|
||||||
|
35h | 017 | x | x | [4x1] | SH20 | Coast WD
|
||||||
|
36h | 024 | x | x | [3x1] | SH21 | Coast WD
|
||||||
|
37h | 041 | x | x | [6x2] | SH22 | Coast WD
|
||||||
|
38h | 049 | x | x | [2x2] | SH23 | Coast WD
|
||||||
|
39h | 118 | x | x | [1x1] | BR1 | Bush
|
||||||
|
3Ah | 134 | x | x | [1x1] | BR2 | Bush
|
||||||
|
3Bh | 150 | x | x | [1x1] | BR3 | Cactus
|
||||||
|
3Ch | 166 | x | x | [1x1] | BR4 | Cactus
|
||||||
|
3Dh | 181 | x | x | [1x1] | BR5 | ??? Purple square (bug ?)
|
||||||
|
3Eh | 196 | x | x | [2x2] | BR6 | Bushes
|
||||||
|
3Fh | 210 | x | x | [2x2] | BR7 | Bushes
|
||||||
|
40h | 223 | x | x | [3x2] | BR8 | Bushes
|
||||||
|
41h | 234 | x | x | [3x2] | BR9 | Bushes
|
||||||
|
42h | 016 | x | x | [2x1] | BR10 | ??? Purple squares (bug ?)
|
||||||
|
43h | 105 | 073 | x | [1x1] | P01 | Bones / Wall (3)
|
||||||
|
44h | 121 | 092 | x | [1x1] | P02 | Bones / Wall (3)
|
||||||
|
45h | 137 | 111 | x | [1x1] | P03 | Mud / UFO (3) (6)
|
||||||
|
46h | 153 | 130 | x | [1x1] | P04 | Rock / UFO (3) (6)
|
||||||
|
47h | 169 | x | x | [2x2] | P05 | Gray Sand
|
||||||
|
48h | 184 | x | x | [6x4] | P06 | Gray Sand
|
||||||
|
49h | 199 | 179 | 178 | [4x2] | P07 | Mud
|
||||||
|
4Ah | x | 194 | 194 | [3x2] | P08 | Mud
|
||||||
|
4Bh | x | 045 | 045 | [3x2] | SH16 | Fjord WU
|
||||||
|
4Ch | 072 | 047 | 047 | [2x2] | SH17 | Water (anim.)
|
||||||
|
4Dh | 078 | 049 | 049 | [2x2] | SH18 | Water (anim.)
|
||||||
|
4Eh | 084 | x | x | [3x2] | SH19 | Coast WD
|
||||||
|
4Fh | x | 116 | 114 | [3x2] | P13 | Destroyed House
|
||||||
|
50h | x | 134 | 131 | [2x1] | P14 | Walls
|
||||||
|
51h | x | x | 148 | [4x2] | P15 | Snow
|
||||||
|
52h | 001 | 006 | 006 | [1x1] | B1 | Rock
|
||||||
|
53h | 003 | 008 | 008 | [2x1] | B2 | Rock
|
||||||
|
54h | x | 010 | 010 | [3x1] | B3 | Rock
|
||||||
|
55h | 004 | x | x | [1x1] | B4 | ?? Rock (7)
|
||||||
|
56h | 005 | x | x | [1x1] | B5 | ?? Rock (7)
|
||||||
|
57h | 006 | x | x | [1x1] | B6 | ?? Rock (7)
|
||||||
|
58h | x | 175 | 174 | [3x3] | SH6 | Coast WD
|
||||||
|
59h | x | 191 | 191 | [2x2] | SH7 | Coast Corner W-N External
|
||||||
|
5Ah | x | 205 | 206 | [3x3] | SH8 | Coast Corner S-E Ext
|
||||||
|
5Bh | x | 215 | 217 | [3x3] | SH9 | Coast Corner W-S Ext
|
||||||
|
5Ch | x | 012 | 011 | [2x2] | SH10 | Coast Corner N-E Ext
|
||||||
|
5Dh | 104 | 072 | 073 | [2x2] | D01 | Road Bottom End
|
||||||
|
5Eh | 120 | 091 | 091 | [2x2] | D02 | Road Left End
|
||||||
|
5Fh | 136 | 110 | 109 | [1x2] | D03 | Road Top End
|
||||||
|
60h | 152 | 129 | 127 | [2x2] | D04 | Road Right End
|
||||||
|
61h | 168 | 146 | 143 | [3x4] | D05 | Road S-N
|
||||||
|
62h | 183 | 162 | 160 | [2x3] | D06 | Road S-N
|
||||||
|
63h | 198 | 178 | 177 | [3x2] | D07 | Road S-N
|
||||||
|
64h | 211 | 193 | 193 | [3x2] | D08 | Road S-N
|
||||||
|
65h | 224 | 207 | 208 | [4x3] | D09 | Road W-E
|
||||||
|
66h | 095 | 063 | 063 | [4x2] | D10 | Road W-E
|
||||||
|
67h | 107 | 077 | 077 | [2x3] | D11 | Road W-E
|
||||||
|
68h | 123 | 096 | 095 | [2x2] | D12 | Road W-E
|
||||||
|
69h | 139 | 115 | 113 | [4x3] | D13 | Road Wu-Ed
|
||||||
|
6Ah | 156 | 133 | 130 | [3x3] | D14 | Road T N--W+E (4)
|
||||||
|
6Bh | 171 | 150 | 147 | [3x3] | D15 | Road Y S--N+E (4)
|
||||||
|
6Ch | 186 | 166 | 164 | [3x3] | D16 | Road Y S--N+E
|
||||||
|
6Dh | 201 | 183 | 182 | [3x2] | D17 | Road T S--W+E
|
||||||
|
6Eh | 214 | 198 | 198 | [3x3] | D18 | Road T W--N+S
|
||||||
|
6Fh | 227 | 210 | 211 | [3x3] | D19 | Road + W-N-E-S
|
||||||
|
70h | 097 | 067 | 067 | [3x3] | D20 | Road Corner N-E
|
||||||
|
71h | 109 | 081 | 081 | [3x2] | D21 | Road Corner S-E
|
||||||
|
72h | 125 | 100 | 099 | [3x3] | D22 | Road Corner W-S
|
||||||
|
73h | 141 | 120 | 118 | [3x3] | D23 | Road Corner W-N
|
||||||
|
74h | 158 | 138 | 135 | [3x3] | D24 | Road Diagonal NW-SE (5)
|
||||||
|
75h | 173 | 154 | 152 | [3x3] | D25 | Road Diag NW-SE
|
||||||
|
76h | 188 | 170 | 169 | [2x2] | D26 | Road Diag NW-SE (Conn.) (5)
|
||||||
|
77h | 203 | 187 | 187 | [2x2] | D27 | Road Diag NW-SE (Conn.)
|
||||||
|
78h | 217 | 201 | 202 | [2x2] | D28 | Road Corner W-SE (Conn.)
|
||||||
|
79h | 229 | 212 | 214 | [2x2] | D29 | Road Corner N-SE (Conn.)
|
||||||
|
7Ah | 100 | 069 | 070 | [2x2] | D30 | Road Y SE--N+W (Conn.)
|
||||||
|
7Bh | 112 | 083 | 083 | [2x2] | D31 | Road Corner E-NW (Conn.)
|
||||||
|
7Ch | 128 | 102 | 101 | [2x2] | D32 | Road Corner S-NW (Conn.)
|
||||||
|
7Dh | 144 | 122 | 120 | [2x2] | D33 | Road Y NW--S+E (Conn.)
|
||||||
|
7Eh | 161 | 140 | 137 | [3x3] | D34 | Road Diag SW-NE
|
||||||
|
7Fh | 176 | 156 | 154 | [3x3] | D35 | Road Diag SW-NE
|
||||||
|
80h | 191 | 172 | 171 | [2x2] | D36 | Road Diag SW-NE (Conn.)
|
||||||
|
81h | 206 | 189 | 189 | [2x2] | D37 | Road Diag SW-NE (Conn.)
|
||||||
|
82h | 220 | 203 | 204 | [2x2] | D38 | Road Corner E-SW (Conn.)
|
||||||
|
83h | 232 | 214 | 216 | [2x2] | D39 | Road Corner N-SW (Conn.)
|
||||||
|
84h | 103 | 071 | 072 | [2x2] | D40 | Road Y SW--N+E (Conn.)
|
||||||
|
85h | 115 | 085 | 085 | [2x2] | D41 | Road Corner W-NE (Conn.)
|
||||||
|
86h | 131 | 104 | 103 | [2x2] | D42 | Road Corner S-NE (Conn.)
|
||||||
|
87h | 147 | 124 | 122 | [2x2] | D43 | Road Y NE--W+S (Conn.)
|
||||||
|
88h | x | 017 | 016 | [5x4] | RV01 | River W-E
|
||||||
|
89h | x | 023 | 022 | [5x3] | RV02 | River W-E
|
||||||
|
8Ah | x | 030 | 030 | [4x4] | RV03 | River Wu-Ed
|
||||||
|
8Bh | x | 036 | 036 | [4x4] | RV04 | River Wd-Eu
|
||||||
|
8Ch | x | 041 | 041 | [3x3] | RV05 | River N-S
|
||||||
|
8Dh | x | 044 | 044 | [3x2] | RV06 | River N-S
|
||||||
|
8Eh | x | 046 | 046 | [3x2] | RV07 | River N-S
|
||||||
|
8Fh | x | 048 | 048 | [2x2] | RV08 | River Corner S-E
|
||||||
|
90h | x | 052 | 052 | [2x2] | RV09 | River Corner W-S
|
||||||
|
91h | x | 014 | 013 | [2x2] | RV10 | River Corner N-E
|
||||||
|
92h | x | 020 | 019 | [2x2] | RV11 | River Corner W-N
|
||||||
|
93h | x | 026 | 025 | [3x4] | RV12 | River Y N--W+S
|
||||||
|
94h | x | 032 | 032 | [4x4] | RV13 | River Y Eu--W+S
|
||||||
|
95h | 055 | x | x | [4x3] | RV14 | River W-E
|
||||||
|
96h | 060 | x | x | [4x3] | RV15 | River W-E
|
||||||
|
97h | 067 | x | x | [6x4] | RV16 | River Wd-Eu
|
||||||
|
98h | 073 | x | x | [6x5] | RV17 | River Wu-Ed
|
||||||
|
99h | 079 | x | x | [4x4] | RV18 | River N-S
|
||||||
|
9Ah | 085 | x | x | [4x4] | RV19 | River N-S
|
||||||
|
9Bh | 018 | x | x | [6x8] | RV20 | River Nr-Sl
|
||||||
|
9Ch | 025 | x | x | [5x8] | RV21 | River Nl-Sr
|
||||||
|
9Dh | 042 | x | x | [3x3] | RV22 | River Corner E-S
|
||||||
|
9Eh | 050 | x | x | [3x3] | RV23 | River Corner W-S
|
||||||
|
9Fh | 057 | x | x | [3x3] | RV24 | River Corner N-E
|
||||||
|
A0h | 062 | x | x | [3x3] | RV25 | River Corner N-W
|
||||||
|
A1h | 009 | 002 | 004 | [3x3] | FORD1 | River Crossing (Road W-E)
|
||||||
|
A2h | 010 | 003 | 005 | [3x3] | FORD2 | River Crossing (Road N-S)
|
||||||
|
A3h | 047 | 057 | 057 | [3x3] | FALLS1 | Falls W-E
|
||||||
|
A4h | 048 | 058 | 058 | [3x2] | FALLS2 | Falls N-S
|
||||||
|
A5h | x | 218 | 220 | [4x4] | BRIDGE1 | Bridge SW-NE
|
||||||
|
A6h | x | 059 | 059 | [4x4] | BRIDGE1D | Fallen Bridge SW-NE
|
||||||
|
A7h | x | 219 | 221 | [5x5] | BRIDGE2 | Bridge NW-SE
|
||||||
|
A8h | x | 060 | 060 | [5x5] | BRIDGE2D | Fallen Bridge NW-SE
|
||||||
|
A9h | 236 | x | x | [6x5] | BRIDGE3 | Bridge SW-NE
|
||||||
|
AAh | 092 | x | x | [6x5] | BRIDGE3D | Fallen Bridge SW-NE
|
||||||
|
ABh | 237 | x | x | [6x4] | BRIDGE4 | Bridge NW-SE
|
||||||
|
ACh | 093 | x | x | [6x4] | BRIDGE4D | Fallen Bridge NW-SE
|
||||||
|
ADh | 056 | x | x | [3x3] | SH24 | Fjord WD
|
||||||
|
AEh | 061 | x | x | [3x2] | SH25 | Coast WU
|
||||||
|
AFh | 068 | x | x | [3x2] | SH26 | Coast WU
|
||||||
|
B0h | 074 | x | x | [4x1] | SH27 | Coast WU
|
||||||
|
B1h | 080 | x | x | [3x1] | SH28 | Coast WU
|
||||||
|
B2h | 086 | x | x | [6x2] | SH29 | Coast WU
|
||||||
|
B3h | 019 | x | x | [2x2] | SH30 | Coast WU
|
||||||
|
B4h | 027 | x | x | [3x3] | SH31 | Fjord WU
|
||||||
|
B5h | x | x | 165 | [2x2] | P16 | Snow
|
||||||
|
B6h | x | x | 183 | [4x2] | P17 | Snow
|
||||||
|
B7h | x | x | 199 | [4x3] | P18 | Snow
|
||||||
|
B8h | x | x | 212 | [4x3] | P19 | Snow
|
||||||
|
B9h | x | x | 068 | [4x3] | P20 | Snow
|
||||||
|
BAh | x | 038 | 038 | [3x3] | SH34 | Coast WR
|
||||||
|
BBh | x | 043 | 043 | [3x3] | SH35 | Coast WL
|
||||||
|
BCh | 069 | x | x | [1x1] | SH36 | Coast Corner S-E Int
|
||||||
|
BDh | 075 | x | x | [1x1] | SH37 | Coast Corner W-S Int
|
||||||
|
BEh | 081 | x | x | [1x1] | SH38 | Coast Corner N-E Int
|
||||||
|
BFh | 087 | x | x | [1x1] | SH39 | Coast Corner N-W Int
|
||||||
|
C0h | 020 | x | x | [3x3] | SH40 | Coast Corner S-E Int
|
||||||
|
C1h | 028 | x | x | [3x3] | SH41 | Coast Corner N-W Int
|
||||||
|
C2h | 043 | x | x | [1x2] | SH42 | Coast WL
|
||||||
|
C3h | 051 | x | x | [1x3] | SH43 | Coast WL
|
||||||
|
C4h | 058 | x | x | [1x3] | SH44 | Coast WR
|
||||||
|
C5h | 063 | x | x | [1x2] | SH45 | Coast WR
|
||||||
|
C6h | 070 | x | x | [3x3] | SH46 | Coast Corner S-E Int
|
||||||
|
C7h | 076 | x | x | [3x3] | SH47 | Coast Corner S-E Int
|
||||||
|
C8h | 082 | x | x | [3x3] | SH48 | Coast Corner N-E Int
|
||||||
|
C9h | 088 | x | x | [3x3] | SH49 | Coast Corner N-W Int
|
||||||
|
CAh | 021 | x | x | [4x3] | SH50 | Coast Corner S-E Ext
|
||||||
|
CBh | 029 | x | x | [4x3] | SH51 | Coast Corner W-S Ext
|
||||||
|
CCh | 044 | x | x | [4x3] | SH52 | Coast Corner N-E Ext
|
||||||
|
CDh | 052 | x | x | [4x3] | SH53 | Coast Corner N-W Ext
|
||||||
|
CEh | 059 | x | x | [3x2] | SH54 | Coast WD
|
||||||
|
CFh | 064 | x | x | [3x2] | SH55 | Coast WD
|
||||||
|
D0h | 071 | x | x | [3x2] | SH56 | Coast WU
|
||||||
|
D1h | 077 | x | x | [3x2] | SH57 | Coast WU
|
||||||
|
D2h | 083 | x | x | [2x3] | SH58 | Coast WR
|
||||||
|
D3h | 089 | x | x | [2x3] | SH59 | Coast WR
|
||||||
|
D4h | 022 | x | x | [2x3] | SH60 | Coast WL
|
||||||
|
D5h | 030 | x | x | [2x3] | SH61 | Coast WL
|
||||||
|
D6h | 045 | x | x | [6x1] | SH62 | Coast WD
|
||||||
|
D7h | 053 | x | x | [4x1] | SH63 | Coast WD
|
||||||
|
|
||||||
|
|
||||||
|
!! Warning !!
|
||||||
|
Values from D8h-FEh will cause the game to crash (it just locks up on
|
||||||
|
my computer)!!!
|
||||||
|
|
||||||
|
The value FFh indicates the default terrain (I think the 4x4 template is
|
||||||
|
used).
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
(0a) There may be some errors in this table because I typed it in a hurry
|
||||||
|
(you don't know how much time it takes), so if you find any errors
|
||||||
|
please report them to me.
|
||||||
|
(0b) The names are taken from the GAME.DAT file. I matched them with the
|
||||||
|
files in the theater mix files. The complete filenames are the names
|
||||||
|
above plus an extension that depends on the theater (.DES, .TEM, .WIN).
|
||||||
|
(1) For Coasts, WD, WU, WL, and WR mean : Water on the bottom
|
||||||
|
(Down), Top (Up), left and right.
|
||||||
|
(2) For cliffs and roads the two letters indicate from which to which side
|
||||||
|
the Road (or cliff) goes. The lowercase letter means up, down, left,
|
||||||
|
right to indicate in which part of that side it starts.
|
||||||
|
For Example:
|
||||||
|
|
||||||
|
River Wu-Ed :
|
||||||
|
OOOOO
|
||||||
|
rOOOO
|
||||||
|
OrrOO
|
||||||
|
OOOrr
|
||||||
|
OOOOO
|
||||||
|
|
||||||
|
(3) These templates exist in both the DESERT and the TEMPERATE theaters but
|
||||||
|
are not the same. I've put a description of both.
|
||||||
|
|
||||||
|
(4) For Roads:
|
||||||
|
Roads T and Y mean that the road splits in the shape of a T or a Y.
|
||||||
|
E--N+S means it starts from the east edge then splits in two parts, one
|
||||||
|
going to the north and the other to the south edge
|
||||||
|
|
||||||
|
(5) NW or any other corner means that the road ends in that corner and if it
|
||||||
|
says (Conn.), that means that it has an empty tile in that corner.
|
||||||
|
So you have to use the (Conn.) templates to stick together the other
|
||||||
|
ones.
|
||||||
|
|
||||||
|
(6) In TEMPERAT.MIX these two files are buggy, they report there are 67h
|
||||||
|
tiles, but if you look at the index you'll see they all point to the
|
||||||
|
second image which (I think) is of uniform color. Only the first tile is
|
||||||
|
ever used.
|
||||||
|
|
||||||
|
(7) These three templates don't work in C&C (HOM effect), but their graphics
|
||||||
|
exist in the DESERT.MIX file. Do not use them !
|
||||||
|
|
||||||
|
That's all. I hope this info will be used by somebody to make a scenery
|
||||||
|
editor.
|
||||||
|
|
||||||
|
Report any errors to me. Also, if you have any info about other file formats
|
||||||
|
please share it with me.
|
||||||
@@ -43,7 +43,6 @@
|
|||||||
Building:
|
Building:
|
||||||
Dimensions: 1,1
|
Dimensions: 1,1
|
||||||
Footprint: x
|
Footprint: x
|
||||||
BaseNormal: no
|
|
||||||
BuildSounds: constru2.aud, hvydoor1.aud
|
BuildSounds: constru2.aud, hvydoor1.aud
|
||||||
SellSounds: cashturn.aud
|
SellSounds: cashturn.aud
|
||||||
RenderBuilding:
|
RenderBuilding:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Packages:
|
|||||||
mods/cnc/packages/sounds.mix
|
mods/cnc/packages/sounds.mix
|
||||||
mods/cnc/packages/tempicnh.mix
|
mods/cnc/packages/tempicnh.mix
|
||||||
mods/cnc/packages/updatec.mix
|
mods/cnc/packages/updatec.mix
|
||||||
|
mods/cnc/packages/temperat.mix
|
||||||
# Cannot qualify the RA names because they may live inside a mix
|
# Cannot qualify the RA names because they may live inside a mix
|
||||||
~main.mix
|
~main.mix
|
||||||
redalert.mix
|
redalert.mix
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ World:
|
|||||||
PaletteFromFile@terrain_temperat:
|
PaletteFromFile@terrain_temperat:
|
||||||
Name: terrain
|
Name: terrain
|
||||||
Theater: temperat
|
Theater: temperat
|
||||||
Filename: temperat_ra.pal
|
Filename: temperat.pal
|
||||||
PaletteFromFile@player_temperat:
|
PaletteFromFile@player_temperat:
|
||||||
Name: player
|
Name: player
|
||||||
Theater: temperat
|
Theater: temperat
|
||||||
|
|||||||
Reference in New Issue
Block a user