About PoP2 custom rooms

About PR usage and development, and about the POP format.

Moderator: English Moderator Team

Post Reply
The Prince of Persia
The Prince of Persia
Posts: 1554
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

About PoP2 custom rooms

Post by David » September 11th, 2014, 8:54 am

This does not seem to be documented anywhere, so I will post it here.

When is a room a custom room?

If one of the tiles has any of the top 2 bits of its second modifier byte set.
(That is, if it's AND-ed with 0xC0, the result is not zero.)
In the disassembly: seg004:0295 -- Note that it uses 0xC000, because the first two modifiers are read together as a 16-bit number.

What happens if a room is a custom room?

From the current leveltype.DAT, load a CUST resource with ID = (roomnumber+159)*25 = 4000 + (roomnumber-1) * 25
In the disassembly: seg004:02D7

What is in that resource?

It consists of a header (0x1C bytes) and a list of image placements (0x19 bytes each)

Their structure is: (db = 1-byte, dw = 2-byte)

Code: Select all

0000 cust_head_type  struc ; (sizeof=0x1C)
0000 num_images      db ? ; number of image placements
0001 room_unique_id  db ?
0002 image_base      dw ? ; ID of first loaded image
0004 image_count     dw ? ; number of loaded images
0006 field_6         dw ?
0008 first_sound     dw ? ; ID of first loaded sound
000A last_sound      dw ? ; ID of last loaded sound
000C field_C         dw ?
000E field_E         dw ?
0010 field_10        db ?
0011 field_11        db ?
0012 field_12        db ?
0013 field_13        db ?
0014 field_14        db ?
0015 field_15        db ?
0016 field_16        db ?
0017 field_17        db ?
0018 field_18        db ?
0019 field_19        db ?
001A field_1A        db ?
001B field_1B        db ?
001C cust_head_type  ends

0000 cust_image_type struc ; (sizeof=0x19)
0000 id              db ? ; add image_base to get the resource ID
0001 xpos            dw ?
0003 ypos            dw ?
0005 layer           db ?
0006 blitter         db ?
0007 image_id?       dw ?
0009 field_9         dw ?
000B clip_top	     dw	?
000D clip_left	     dw	?
000F clip_bottom     dw	?
0011 clip_right	     dw	?
0013 clip_on?	     db	?
0014 wipe?           db ?
0015 field_15        db ?
0016 field_16        db ?
0017 field_17        db ?
0018 field_18        db ?
0019 cust_image_type ends
The header contains a unique id.
Based on this id, certain things may happen when the kid enters or leaves this room.

There is a table in the exe, which contains a pointer for each room id.
At the pointed address, there is an array of 7 function pointers.
(Note that some rooms share the same array!)
The first function is called on entry, the second is called on exit. The others are always NULL and don't seem to be used.
In the disassembly: data:037A

How are tiles drawn in a custom room?

The top 2 bits of the aforementioned modifier byte specify how to draw each tile:

00: draw tile normally (front+back+backwall)
01: draw front layer only
10: draw front+back only (no backwall)
11: don't draw (except overlaid front)

The potion behaves differently: 00,01,10 mean: base+bubbles only, all bubbles are displayed on top of each other.

Post Reply