author | ecalot
<ecalot> 2006-01-22 19:10:22 UTC |
committer | ecalot
<ecalot> 2006-01-22 19:10:22 UTC |
parent | 4bdc11b6d2c3c13378e62b16fab494d8764d6e3a |
FP/doc/FormatSpecifications | +105 | -130 |
FP/doc/FormatSpecifications.tex | +105 | -130 |
diff --git a/FP/doc/FormatSpecifications b/FP/doc/FormatSpecifications index 9e5c253..ed62f45 100644 --- a/FP/doc/FormatSpecifications +++ b/FP/doc/FormatSpecifications @@ -35,6 +35,9 @@ Table of Contents 5.1. General file specs, index and checksums .......................... 790 5.1.1. The master index ............................................... 817 5.1.2. The slave indexes .............................................. 855 +5.2. Levels ........................................................... 855 +5.2.1 Room mapping .................................................... 855 +5.2.2 Door events ..................................................... 855 6. PLV v1.0 Format Specifications ..................................... 875 6.1. User data ........................................................ 901 6.2. Allowed Date format .............................................. 931 @@ -244,11 +247,11 @@ Table of Contents LZG_LR has some kind of variant of the LZ77 algorithm (the sliding windows algorithm), here we named it LZG in honour of Lance Groody, the original coder. - After uncompressed it may be handled as RAW_LR. + After decompressed it may be handled as RAW_LR. LZG_UD Uses LZG compression but is drawn from top to bottom as RLE_UD 4.2.2.1 Run length encoding (RLE) - The first byte is allways a control byte, the format is SC. If the control + The first byte is always a control byte, the format is SC. If the control byte is negative, then the next byte must be repeated n times as the bit inverted control byte says, after the next byte (the one that was repeated) @@ -279,97 +282,44 @@ Table of Contents window starting with the S'th byte. After all the maskbyte is read and processed, the following input byte is - another maskbyte. Use the same procedure to finish uncompressing the file. - - This version of the algorithm is limited to 1024 bytes due to the slide - window size. In case you want to know the full algorithm and see how it - works for bigger images you should use the source, Luke. - - This is the full uncompression function source. Note that this is part of - PR that is under the GPL license. The variables \xabR\xbb and \xabS\xbb are \xabrep\xbb and - \xabloc\xbb respectively. The array output is the output stream and oCursor is - the current location. The input array and iCursor variable had the same - meaning for the input stream. The algorithm ends when the full input has - been processed. The maskbyte must remain with 0 for the unexistent bytes, - so if you find the maskbyte not null, it is possible that the input array - wasn't a LZG compressed stream. In that case that non-zero value is going - to be returned. This is the only internal way to detect an error in the - compression layer. All the data that has the latest maskbyte without this - issue will be detected as valid and unpacked normally. - - Algorithm 4.1: LZG - ~~~~~~~~~~~~~~~~~~ - - /* A big number (the output must be less that that) */ - #define LZG_MAX_MEMSIZE 32001 - - /* modulus to be used in the 10 bits of the algorithm */ - #define LZG_WINDOW_SIZE 0x400 /* =1024=1<<10 */ - - /* LZG expansion algorithm sub function */ - unsigned char popBit(unsigned char *byte) { - register unsigned char bit=(*byte)&1; - (*byte)>>=1; - return bit; - } - - /* Expands LZ Groody algorithm. This is the core of PR. - * returns 0 on success, non-zero on possible data corruption - */ - int expandLzg(const unsigned char* input, int inputSize, - unsigned char* output, int *outputSize) { - - int loc, oCursor=0, iCursor=0; - unsigned char maskbyte=0, rep, k; - - /* clean output garbage */ - for(loc=LZG_MAX_MEMSIZE;loc--;output[loc]=0); - - /* main loop */ - while (iCursor<inputSize) { - maskbyte=input[iCursor++]; - for (k=8;k&&(iCursor<inputSize);k--) { - if (popBit(&maskbyte)) { - output[oCursor++]=input[iCursor++]; /* copy input to output */ - } else { - /* - * loc: - * 10 bits for the slide iCursorition (S). Add 66 to this number. - * rep: - * 6 bits for the repetition number (R). Add 3 to this number. - */ - loc= 66 + ((input[iCursor] & 0x03 /*00000011*/) <<8) + input[iCursor+1]; - rep= 3 + ((input[iCursor] & 0xfc /*11111100*/) >>2); - - iCursor+=2; - - while (rep--) { /* repeat pattern in output */ - loc=loc%LZG_WINDOW_SIZE; /* loc is in range 0-1023 */ - - /* - * delta is ((loc-oCursor)%LZG_WINDOW_SIZE) - * this is the offset where the bytes will be looked for - * in the simple algorithm it is allways negative - * in bigger images it can be iCursoritive - * - * this value is inside the range -1023 to 1023. - * if loc>oCursor the result is iCursoritive - * if loc<oCursor the result is negative - */ - - output[oCursor]=output[oCursor+((loc-oCursor)%LZG_WINDOW_SIZE)]; - - oCursor++; - loc++; - } - } - } - } - - *outputSize=oCursor; - return maskbyte; - } - + another maskbyte. Use the same procedure to finish decompressing the file. + Remaining unused maskbits should be zeros to validate the file. + + This is the modus operandi of the compression algorithm + + For each input byte we take a window containing the 1023 previous bytes. + If the window goes out of bounds (ie, when the current input byte is + before position 1024), we consider it filled with zeros. + + 00000000000000000000******************************** + ^ ^ + input start current input byte + |--------------------------------| + window size=1023 + + The algorithm works as follows: + + While there is unread input data: + Create a maskbyte. + For each bit in the maskbyte (and there is still unread input data): + Compare the following input bytes with the bytes in the window, + and search the longest pattern that is equal to the next bytes. + If we found a pattern of length n > 2: + Assign 0 to the current bit of the maskbyte. + In the next 2 bytes of the output, specify the relative + position and length of the pattern. + Advance output pointer by 2. + Advance input pointer by n. + Else: + Assign 1 to the current bit of the maskbyte. + Copy the current input byte in the next output byte. + Advance output pointer by 1. + Advance input pointer by 1. + + For a better understanding of the algorithm we strongly recommend to read + the PR source files lzg_uncompress.c and lzg_compress.c that may be + located at http://www.cvs.fp.princed.com.ar in the PR repository module. + 4.3. Palettes Palettes have 100 bytes allways, after 4 bytes from the beginning the first 16 records of 3 bytes are the VGA colours stored in the RGB-18 bits @@ -441,13 +391,13 @@ Table of Contents It is reserved 1 byte from the wall block and one from the pop1_background block for each tile. To locate the appropriate tile you have to do the following calculation: tile=(room-1)*30+tileOffset where tileOffset is a - number from 0 to 29 that means a tile from 0 to 9 if in the upper stage, from - 10 to 19 if in the middle stage and 20 to 29 if in the bottom stage. + number from 0 to 29 that means a tile from 0 to 9 if in the upper stage, + from 10 to 19 if in the middle stage and 20 to 29 if in the bottom stage. We define this as the location format and will be used also in the start position. Allways looking from the left to the right. - So there is a wall and pop1_background byte for each tile in the level and this - is stored this way. + So there is a wall and pop1_background byte for each tile in the level and + this is stored this way. The wall part of the tile stores the main tile form according to the table below. Note that those are just a limited number of tiles, each code has a @@ -813,13 +763,13 @@ Table of Contents call this index the \xabmaster index\xbb and the sub index the \xabslave indexes\xbb. Slave indexes are the real file contents index. -5.1.1. The master index +5.1.1 The master index The master index is made with: - Offset HighDataOffset, size 2, type US: NumberOfSlaveIndexes (the number of the high data sections) - - Offset HighDataOffset+2, size NumberOfSlaveIndexes*6: The master index record - (a list of NumberOfSlaveIndexes blocks of 6-bytes-length index - record each corresponding to one slave index) + - Offset HighDataOffset+2, size NumberOfSlaveIndexes*6: The master index + record (a list of NumberOfSlaveIndexes blocks of 6-bytes-length + index record each corresponding to one slave index) The 6-bytes-length index record (one per item): Size = 6 bytes - Relative offset 0, size 4, type sting: 4 ASCII bytes string denoting @@ -832,10 +782,10 @@ Table of Contents points to). There are different 4 bytes ASCII strings section IDs. When the string is - less than 4 bytes, they are ended in hex 0x00 is used. We will denote it with - the cardinal # symbol. The character order is inverted, so for example the - text SLAP becomes PALS, MARF becomes FRAM, #### becomes empty or - RCS# becomes SCR. They must be un upper case. + less than 4 bytes, they are ended in hex 0x00 is used. We will denote it + with the cardinal # symbol. The character order is inverted, so for + example the text SLAP becomes PALS, MARF becomes FRAM, #### becomes empty + or RCS# becomes SCR. They must be un upper case. Table 5.1: Section ID strings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -859,14 +809,14 @@ Table of Contents txt4 4TXT Text #### Levels -5.1.2. The slave indexes +5.1.2 The slave indexes All encapsulated sections are indexes. The slave index is made with: - Offset SlaveIndexOffset, size 2, type US: NumberOfItems (the number of the records referring to the file data) - - Offset SlaveIndexOffset+2, size NumberOfItems*11: The slave index record - (a list of NumberOfItems blocks of 11-bytes-length index record - each corresponding to one slave index) + - Offset SlaveIndexOffset+2, size NumberOfItems*11: The slave index + record (a list of NumberOfItems blocks of 11-bytes-length index + record each corresponding to one slave index) The 11-bytes-length slave index record (one per item): Size = 11 bytes - Relative offset 0, size 2, type US: Item ID @@ -891,7 +841,7 @@ Table of Contents ~~~~~~ ~~~~~~ ~~~~~~~~~~ 960 0 wall 3840 960 pop2_background - 1280 4800 unknown I (doors) + 1280 4800 pop2_doors 128 6080 links (as explained in section 4.4.3 but having 32 rooms) 32 6208 unknown II 3 6240 start_position (as explained in section 4.4.5) @@ -906,12 +856,12 @@ Table of Contents 31) because the 0 is be reserved to the null-room. The wall block has 32 sub-blocks inside. Each sub-block has a size of 30 - bytes and has a room associated. For each byte in this room there is a tile - in the game. Each byte has a code to represent a tile. There are additional - attributes to this tile also. + bytes and has a room associated. For each byte in this room there is a + tile in the game. Each byte has a code to represent a tile. There are + additional attributes to this tile also. - To locate the 7th tile in the bottom floor of the room 27 you have to do the - same calculation as in 4.4.2: + To locate the 7th tile in the bottom floor of the room 27 you have to do + the same calculation as in 4.4.2: tile=(room-1)*30+tileOffset=(27-1)*30+2*10+7=807 @@ -921,16 +871,16 @@ Table of Contents Hex Binary Group Description ~~~~ ~~~~~~ ~~~~~ ~~~~~~~~~~~ 0x00 000000 (?) Empty - 0x01 000001 (?) Floor + 0x01 000001 floor Floor 0x02 000010 (?) Wall with spikes 0x03 000011 (?) One floor pillar - 0x04 000100 (?) Door - 0x06 000110 (?) Loose I + 0x04 000100 door Door + 0x06 000110 (?) Loose hidden 0x07 000111 (?) Linked loose 0x08 001000 (?) Big pillar base 0x09 001001 (?) Big pillar top 0x0A 001010 (?) Potion - 0x0B 001011 (?) Loose II + 0x0B 001011 (?) Loose not hidden 0x0E 001110 (?) Debris 0x10 010000 (?) Exit door left 0x11 010001 (?) Exit door right @@ -940,26 +890,50 @@ Table of Contents 0x17 010111 (?) Lava (left) 0x18 011000 (?) Lava (right) 0x1B 011011 (?) Special activator (?) - 0x21 100001 (?) Stalactites I + 0x20 100000 (?) Debris & torch + 0x21 100001 floor Exit door left-top 0x22 100010 (?) Activator (floor shooter or door) - 0x23 100011 (?) Stalactites II - 0x24 100100 (?) Floor shooter + 0x23 100011 floor Exit door left-right + 0x24 100100 door Floor shooter The pop2_background is an expansion if the pop1_background and it is sized 4 times bigger. For each tile there are 4 additional bytes in the - pop2_background block to specify further actions or attributes. - This block is sized 4 bytes/tile * 10 tiles/floor * 3 floors/room * 32 rooms - that is 3840 bytes. + pop2_background block to specify further actions or attributes. This block + is sized 4 bytes/tile * 10 tiles/floor * 3 floors/room * 32 rooms that is + 3840 bytes. We call background mask to each block of 4 bytes associated to a tile. To locate a background mask you have to do the following operation: 960+(room-1)*30*4+tileOffset*4 - Background masks are stored consecutively each after another until the 960 - tiles are specified. + Background masks are stored consecutively each after another until the + 960 tiles are specified. + + The first byte is an unsigned char association to one of the 256 door + event registers (see section 5.2.2) if the tile is an activator or 0 in + any other case. - The second byte in a background mask is the attribute byte. For example 0x18 - modifies the tile 0x01 and adds two small stalactites. + The second byte in a background mask is the attribute byte. For example + 0x18 modifies the tile 0x01 and adds two small stalactites. - We believe the doors uses the 3rd or 4th byte. + We believe the special images uses the 3rd or 4th byte. + +5.2.2 Door events + This section explains how doors are handled and specifies the block + pop2_door. + + The pop2_door block has 1280 bytes. It is divided in 256 registers of + 5 bytes called door events. Like pop1 events have associations to doors + and activate them. In POP2 events can also activate a floor shooter. + + An event is triggered when an activator (0x22) is pressed. As it is + specified in the section 5.2.1, the first byte of the attribute mask + belonging to an activator tile points the activator to a door event. + There is a maximum of 256 events because of the unsigned char of the first + byte if the attribute mask in the pop2_background block and the 256 + registers in the pop2_door block. + + Each event register is of the form "XX YY TT FD FD" which activates the + normal door (0x04), right exit door (0x11) or shooter (0x24) in position + YY of the screen XX. TT is 00 for normal activation and FF for exit doors. 6. PLV v1.0 Format Specifications @@ -1115,6 +1089,7 @@ Table of Contents Images . . . . . . . . . . . . . . . . . . . . . . . Tammo Jan Dijkema RLE Compression . . . . . . . . . . . . . . . . . . . Tammo Jan Dijkema LZG Compression . . . . . . . . . . . . . . . . . . . . . Anke Balderer + Diego Essaya Sounds . . . . . . . . . . . . . . . . . . . . . . . Christian Lundheim PLV v1.0: diff --git a/FP/doc/FormatSpecifications.tex b/FP/doc/FormatSpecifications.tex index 9e5c253..ed62f45 100644 --- a/FP/doc/FormatSpecifications.tex +++ b/FP/doc/FormatSpecifications.tex @@ -35,6 +35,9 @@ Table of Contents 5.1. General file specs, index and checksums .......................... 790 5.1.1. The master index ............................................... 817 5.1.2. The slave indexes .............................................. 855 +5.2. Levels ........................................................... 855 +5.2.1 Room mapping .................................................... 855 +5.2.2 Door events ..................................................... 855 6. PLV v1.0 Format Specifications ..................................... 875 6.1. User data ........................................................ 901 6.2. Allowed Date format .............................................. 931 @@ -244,11 +247,11 @@ Table of Contents LZG_LR has some kind of variant of the LZ77 algorithm (the sliding windows algorithm), here we named it LZG in honour of Lance Groody, the original coder. - After uncompressed it may be handled as RAW_LR. + After decompressed it may be handled as RAW_LR. LZG_UD Uses LZG compression but is drawn from top to bottom as RLE_UD 4.2.2.1 Run length encoding (RLE) - The first byte is allways a control byte, the format is SC. If the control + The first byte is always a control byte, the format is SC. If the control byte is negative, then the next byte must be repeated n times as the bit inverted control byte says, after the next byte (the one that was repeated) @@ -279,97 +282,44 @@ Table of Contents window starting with the S'th byte. After all the maskbyte is read and processed, the following input byte is - another maskbyte. Use the same procedure to finish uncompressing the file. - - This version of the algorithm is limited to 1024 bytes due to the slide - window size. In case you want to know the full algorithm and see how it - works for bigger images you should use the source, Luke. - - This is the full uncompression function source. Note that this is part of - PR that is under the GPL license. The variables \xabR\xbb and \xabS\xbb are \xabrep\xbb and - \xabloc\xbb respectively. The array output is the output stream and oCursor is - the current location. The input array and iCursor variable had the same - meaning for the input stream. The algorithm ends when the full input has - been processed. The maskbyte must remain with 0 for the unexistent bytes, - so if you find the maskbyte not null, it is possible that the input array - wasn't a LZG compressed stream. In that case that non-zero value is going - to be returned. This is the only internal way to detect an error in the - compression layer. All the data that has the latest maskbyte without this - issue will be detected as valid and unpacked normally. - - Algorithm 4.1: LZG - ~~~~~~~~~~~~~~~~~~ - - /* A big number (the output must be less that that) */ - #define LZG_MAX_MEMSIZE 32001 - - /* modulus to be used in the 10 bits of the algorithm */ - #define LZG_WINDOW_SIZE 0x400 /* =1024=1<<10 */ - - /* LZG expansion algorithm sub function */ - unsigned char popBit(unsigned char *byte) { - register unsigned char bit=(*byte)&1; - (*byte)>>=1; - return bit; - } - - /* Expands LZ Groody algorithm. This is the core of PR. - * returns 0 on success, non-zero on possible data corruption - */ - int expandLzg(const unsigned char* input, int inputSize, - unsigned char* output, int *outputSize) { - - int loc, oCursor=0, iCursor=0; - unsigned char maskbyte=0, rep, k; - - /* clean output garbage */ - for(loc=LZG_MAX_MEMSIZE;loc--;output[loc]=0); - - /* main loop */ - while (iCursor<inputSize) { - maskbyte=input[iCursor++]; - for (k=8;k&&(iCursor<inputSize);k--) { - if (popBit(&maskbyte)) { - output[oCursor++]=input[iCursor++]; /* copy input to output */ - } else { - /* - * loc: - * 10 bits for the slide iCursorition (S). Add 66 to this number. - * rep: - * 6 bits for the repetition number (R). Add 3 to this number. - */ - loc= 66 + ((input[iCursor] & 0x03 /*00000011*/) <<8) + input[iCursor+1]; - rep= 3 + ((input[iCursor] & 0xfc /*11111100*/) >>2); - - iCursor+=2; - - while (rep--) { /* repeat pattern in output */ - loc=loc%LZG_WINDOW_SIZE; /* loc is in range 0-1023 */ - - /* - * delta is ((loc-oCursor)%LZG_WINDOW_SIZE) - * this is the offset where the bytes will be looked for - * in the simple algorithm it is allways negative - * in bigger images it can be iCursoritive - * - * this value is inside the range -1023 to 1023. - * if loc>oCursor the result is iCursoritive - * if loc<oCursor the result is negative - */ - - output[oCursor]=output[oCursor+((loc-oCursor)%LZG_WINDOW_SIZE)]; - - oCursor++; - loc++; - } - } - } - } - - *outputSize=oCursor; - return maskbyte; - } - + another maskbyte. Use the same procedure to finish decompressing the file. + Remaining unused maskbits should be zeros to validate the file. + + This is the modus operandi of the compression algorithm + + For each input byte we take a window containing the 1023 previous bytes. + If the window goes out of bounds (ie, when the current input byte is + before position 1024), we consider it filled with zeros. + + 00000000000000000000******************************** + ^ ^ + input start current input byte + |--------------------------------| + window size=1023 + + The algorithm works as follows: + + While there is unread input data: + Create a maskbyte. + For each bit in the maskbyte (and there is still unread input data): + Compare the following input bytes with the bytes in the window, + and search the longest pattern that is equal to the next bytes. + If we found a pattern of length n > 2: + Assign 0 to the current bit of the maskbyte. + In the next 2 bytes of the output, specify the relative + position and length of the pattern. + Advance output pointer by 2. + Advance input pointer by n. + Else: + Assign 1 to the current bit of the maskbyte. + Copy the current input byte in the next output byte. + Advance output pointer by 1. + Advance input pointer by 1. + + For a better understanding of the algorithm we strongly recommend to read + the PR source files lzg_uncompress.c and lzg_compress.c that may be + located at http://www.cvs.fp.princed.com.ar in the PR repository module. + 4.3. Palettes Palettes have 100 bytes allways, after 4 bytes from the beginning the first 16 records of 3 bytes are the VGA colours stored in the RGB-18 bits @@ -441,13 +391,13 @@ Table of Contents It is reserved 1 byte from the wall block and one from the pop1_background block for each tile. To locate the appropriate tile you have to do the following calculation: tile=(room-1)*30+tileOffset where tileOffset is a - number from 0 to 29 that means a tile from 0 to 9 if in the upper stage, from - 10 to 19 if in the middle stage and 20 to 29 if in the bottom stage. + number from 0 to 29 that means a tile from 0 to 9 if in the upper stage, + from 10 to 19 if in the middle stage and 20 to 29 if in the bottom stage. We define this as the location format and will be used also in the start position. Allways looking from the left to the right. - So there is a wall and pop1_background byte for each tile in the level and this - is stored this way. + So there is a wall and pop1_background byte for each tile in the level and + this is stored this way. The wall part of the tile stores the main tile form according to the table below. Note that those are just a limited number of tiles, each code has a @@ -813,13 +763,13 @@ Table of Contents call this index the \xabmaster index\xbb and the sub index the \xabslave indexes\xbb. Slave indexes are the real file contents index. -5.1.1. The master index +5.1.1 The master index The master index is made with: - Offset HighDataOffset, size 2, type US: NumberOfSlaveIndexes (the number of the high data sections) - - Offset HighDataOffset+2, size NumberOfSlaveIndexes*6: The master index record - (a list of NumberOfSlaveIndexes blocks of 6-bytes-length index - record each corresponding to one slave index) + - Offset HighDataOffset+2, size NumberOfSlaveIndexes*6: The master index + record (a list of NumberOfSlaveIndexes blocks of 6-bytes-length + index record each corresponding to one slave index) The 6-bytes-length index record (one per item): Size = 6 bytes - Relative offset 0, size 4, type sting: 4 ASCII bytes string denoting @@ -832,10 +782,10 @@ Table of Contents points to). There are different 4 bytes ASCII strings section IDs. When the string is - less than 4 bytes, they are ended in hex 0x00 is used. We will denote it with - the cardinal # symbol. The character order is inverted, so for example the - text SLAP becomes PALS, MARF becomes FRAM, #### becomes empty or - RCS# becomes SCR. They must be un upper case. + less than 4 bytes, they are ended in hex 0x00 is used. We will denote it + with the cardinal # symbol. The character order is inverted, so for + example the text SLAP becomes PALS, MARF becomes FRAM, #### becomes empty + or RCS# becomes SCR. They must be un upper case. Table 5.1: Section ID strings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -859,14 +809,14 @@ Table of Contents txt4 4TXT Text #### Levels -5.1.2. The slave indexes +5.1.2 The slave indexes All encapsulated sections are indexes. The slave index is made with: - Offset SlaveIndexOffset, size 2, type US: NumberOfItems (the number of the records referring to the file data) - - Offset SlaveIndexOffset+2, size NumberOfItems*11: The slave index record - (a list of NumberOfItems blocks of 11-bytes-length index record - each corresponding to one slave index) + - Offset SlaveIndexOffset+2, size NumberOfItems*11: The slave index + record (a list of NumberOfItems blocks of 11-bytes-length index + record each corresponding to one slave index) The 11-bytes-length slave index record (one per item): Size = 11 bytes - Relative offset 0, size 2, type US: Item ID @@ -891,7 +841,7 @@ Table of Contents ~~~~~~ ~~~~~~ ~~~~~~~~~~ 960 0 wall 3840 960 pop2_background - 1280 4800 unknown I (doors) + 1280 4800 pop2_doors 128 6080 links (as explained in section 4.4.3 but having 32 rooms) 32 6208 unknown II 3 6240 start_position (as explained in section 4.4.5) @@ -906,12 +856,12 @@ Table of Contents 31) because the 0 is be reserved to the null-room. The wall block has 32 sub-blocks inside. Each sub-block has a size of 30 - bytes and has a room associated. For each byte in this room there is a tile - in the game. Each byte has a code to represent a tile. There are additional - attributes to this tile also. + bytes and has a room associated. For each byte in this room there is a + tile in the game. Each byte has a code to represent a tile. There are + additional attributes to this tile also. - To locate the 7th tile in the bottom floor of the room 27 you have to do the - same calculation as in 4.4.2: + To locate the 7th tile in the bottom floor of the room 27 you have to do + the same calculation as in 4.4.2: tile=(room-1)*30+tileOffset=(27-1)*30+2*10+7=807 @@ -921,16 +871,16 @@ Table of Contents Hex Binary Group Description ~~~~ ~~~~~~ ~~~~~ ~~~~~~~~~~~ 0x00 000000 (?) Empty - 0x01 000001 (?) Floor + 0x01 000001 floor Floor 0x02 000010 (?) Wall with spikes 0x03 000011 (?) One floor pillar - 0x04 000100 (?) Door - 0x06 000110 (?) Loose I + 0x04 000100 door Door + 0x06 000110 (?) Loose hidden 0x07 000111 (?) Linked loose 0x08 001000 (?) Big pillar base 0x09 001001 (?) Big pillar top 0x0A 001010 (?) Potion - 0x0B 001011 (?) Loose II + 0x0B 001011 (?) Loose not hidden 0x0E 001110 (?) Debris 0x10 010000 (?) Exit door left 0x11 010001 (?) Exit door right @@ -940,26 +890,50 @@ Table of Contents 0x17 010111 (?) Lava (left) 0x18 011000 (?) Lava (right) 0x1B 011011 (?) Special activator (?) - 0x21 100001 (?) Stalactites I + 0x20 100000 (?) Debris & torch + 0x21 100001 floor Exit door left-top 0x22 100010 (?) Activator (floor shooter or door) - 0x23 100011 (?) Stalactites II - 0x24 100100 (?) Floor shooter + 0x23 100011 floor Exit door left-right + 0x24 100100 door Floor shooter The pop2_background is an expansion if the pop1_background and it is sized 4 times bigger. For each tile there are 4 additional bytes in the - pop2_background block to specify further actions or attributes. - This block is sized 4 bytes/tile * 10 tiles/floor * 3 floors/room * 32 rooms - that is 3840 bytes. + pop2_background block to specify further actions or attributes. This block + is sized 4 bytes/tile * 10 tiles/floor * 3 floors/room * 32 rooms that is + 3840 bytes. We call background mask to each block of 4 bytes associated to a tile. To locate a background mask you have to do the following operation: 960+(room-1)*30*4+tileOffset*4 - Background masks are stored consecutively each after another until the 960 - tiles are specified. + Background masks are stored consecutively each after another until the + 960 tiles are specified. + + The first byte is an unsigned char association to one of the 256 door + event registers (see section 5.2.2) if the tile is an activator or 0 in + any other case. - The second byte in a background mask is the attribute byte. For example 0x18 - modifies the tile 0x01 and adds two small stalactites. + The second byte in a background mask is the attribute byte. For example + 0x18 modifies the tile 0x01 and adds two small stalactites. - We believe the doors uses the 3rd or 4th byte. + We believe the special images uses the 3rd or 4th byte. + +5.2.2 Door events + This section explains how doors are handled and specifies the block + pop2_door. + + The pop2_door block has 1280 bytes. It is divided in 256 registers of + 5 bytes called door events. Like pop1 events have associations to doors + and activate them. In POP2 events can also activate a floor shooter. + + An event is triggered when an activator (0x22) is pressed. As it is + specified in the section 5.2.1, the first byte of the attribute mask + belonging to an activator tile points the activator to a door event. + There is a maximum of 256 events because of the unsigned char of the first + byte if the attribute mask in the pop2_background block and the 256 + registers in the pop2_door block. + + Each event register is of the form "XX YY TT FD FD" which activates the + normal door (0x04), right exit door (0x11) or shooter (0x24) in position + YY of the screen XX. TT is 00 for normal activation and FF for exit doors. 6. PLV v1.0 Format Specifications @@ -1115,6 +1089,7 @@ Table of Contents Images . . . . . . . . . . . . . . . . . . . . . . . Tammo Jan Dijkema RLE Compression . . . . . . . . . . . . . . . . . . . Tammo Jan Dijkema LZG Compression . . . . . . . . . . . . . . . . . . . . . Anke Balderer + Diego Essaya Sounds . . . . . . . . . . . . . . . . . . . . . . . Christian Lundheim PLV v1.0: