====== Levels ====== Levels are contained in two gzip blocks. e.g.: chimp.raw: level data for Simian Acres chimp_dl.raw: display lists for Simian Acres The level data begins with a header that contains the offsets in the file for all of the level information (RDUs, buildings, vehicles, etc.). The level data file also contains vertices and other data used by the display list that are loaded into segment 08. The display list contains mostly raw F3D commands. The exception is 0xFD G_SETTIMG command which contain indexes to a [[blast_corps:textures#texture_table|texture table]]. At run-time, after the display list is copied to RAM, the texture indexes in the G_SETTIMG are replaced with texture offsets in segment 0x00. ===== List of Levels ===== The function at 0x8025615C is used to lookup and copy the level data files from level ID and is implemented as a switch statement with the following lookup: ^ ID ^ JmpTable ^ Start ^ End ^ Name gzip ^ Level Name | | 0 | 802561B8 | 4ACC10 | 4B8960 | chimp.raw | Simian Acres | | 1 | 80256194 | 4A5660 | 4ACC10 | lagp.raw | Angel City | | 2 | 802561DC | 4B8960 | 4BFD60 | valley.raw | Outland Farm | | 3 | 80256200 | 4BFD60 | 4C3AC0 | fact.raw | Blackridge Works | | 4 | 80256224 | 4C3AC0 | 4D5F90 | dip.raw | Glory Crossing | | 5 | 80256248 | 4D5F90 | 4E2F70 | beetle.raw | Shuttle Gully | | 6 | 8025626C | 4E2F70 | 4E4E80 | bonus1.raw | Salvage Wharf | | 7 | 80256290 | 4E4E80 | 4E7C00 | bonus2.raw | Skyfall | | 8 | 802562B4 | 4E7C00 | 4E8F70 | bonus3.raw | Twilight Foundry | | 9 | 802562D8 | 4E8F70 | 4F5C10 | level9.raw | Crystal Rift | | 10 | 802562FC | 4F5C10 | 500520 | level10.raw | Argent Towers | | 11 | 80256320 | 500520 | 507E80 | level11.raw | Skerries | | 12 | 80256344 | 507E80 | 511340 | level12.raw | Diamond Sands | | 13 | 80256368 | 511340 | 523080 | level13.raw | Ebony Coast | | 14 | 8025638C | 523080 | 52CD00 | level14.raw | Oyster Harbor | | 15 | 802563B0 | 52CD00 | 532700 | level15.raw | Carrick Point | | 16 | 802563D4 | 532700 | 53E9B0 | level16.raw | Havoc District | | 17 | 802563F8 | 53E9B0 | 54A820 | level17.raw | Ironstone Mine | | 18 | 8025641C | 54A820 | 552DE0 | level18.raw | Beeton Tracks | | 19 | 80256440 | 552DE0 | 555000 | level19.raw | J-Bomb | | 20 | 80256464 | 555000 | 560E90 | level20.raw | Jade Plateau | | 21 | 80256488 | 560E90 | 5652D0 | level21.raw | Marine Quarter | | 22 | 802564AC | 5652D0 | 56F3F0 | level22.raw | Cooter Creek | | 23 | 802564D0 | 56F3F0 | 5721E0 | level23.raw | Gibbon's Gate | | 24 | 802564F4 | 5721E0 | 5736E0 | level24.raw | Baboon Catacomb | | 25 | 80256518 | 5736E0 | 57A2C0 | level25.raw | Sleek Streets | | 26 | 8025653C | 57A2C0 | 580B60 | level26.raw | Obsidian Mile | | 27 | 80256560 | 580B60 | 588CE0 | level27.raw | Corvine Bluff | | 28 | 80256584 | 588CE0 | 58BE80 | level28.raw | Sideswipe | | 29 | 802565A8 | 58BE80 | 597B80 | level29.raw | Echo Marches | | 30 | 802565CC | 597B80 | 59B7D0 | level30.raw | Kipling Plant | | 31 | 802565F0 | 59B7D0 | 5A5840 | level31.raw | Falchion Field | | 32 | 80256614 | 5A5840 | 5B0B10 | level32.raw | Morgan Hall | | 33 | 80256638 | 5B0B10 | 5B5A30 | level33.raw | Tempest City | | 34 | 8025665C | 5B5A30 | 5B8BB0 | level34.raw | Orion Plaza | | 35 | 80256680 | 5B8BB0 | 5C4C80 | level35.raw | Glander's Ranch | | 36 | 802566A4 | 5C4C80 | 5CA9C0 | level36.raw | Dagger Pass | | 37 | 802566C8 | 5CA9C0 | 5CCF50 | level37.raw | Geode Square | | 38 | 802566EC | 5CCF50 | 5D1060 | level38.raw | Shuttle Island | | 39 | 80256710 | 5D1060 | 5DC830 | level39.raw | Mica Park | | 40 | 80256734 | 5DC830 | 5E6EE0 | level40.raw | Moon | | 41 | 80256758 | 5E6EE0 | 5EC800 | level41.raw | Cobalt Quarry | | 42 | 8025677C | 5EC800 | 5F3A80 | level42.raw | Moraine Chase | | 43 | 802567A0 | 5F3A80 | 6014B0 | level43.raw | Mercury | | 44 | 802567C4 | 6014B0 | 60A710 | level44.raw | Venus | | 45 | 802567E8 | 60A710 | 613AA0 | level45.raw | Mars | | 46 | 8025680C | 613AA0 | 61DD70 | level46.raw | Neptune | | 47 | 80256830 | 61DD70 | 621AF0 | level47.raw | CMO Intro | | 48 | 80256854 | 621AF0 | 6269E0 | level48.raw | Silver Junction | | 49 | 80256878 | 6269E0 | 630C30 | level49.raw | End Sequence | | 50 | 8025689C | 630C30 | 635700 | level50.raw | Shuttle Clear | | 51 | 802568C0 | 635700 | 63CA10 | level51.raw | Dark Heartland | | 52 | 802568E4 | 63CA10 | 641F30 | level52.raw | Magma Peak | | 53 | 80256908 | 641F30 | 644810 | level53.raw | Thunderfist | | 54 | 8025692C | 644810 | 646080 | level54.raw | Saline Watch | | 55 | 80256950 | 646080 | 647550 | level55.raw | Backlash | | 56 | 80256974 | 647550 | 654FC0 | level56.raw | Bison Ridge | | 57 | 80256998 | 654FC0 | 660950 | level57.raw | Ember Hamlet | | 58 | 802569BC | 660950 | 665F80 | level58.raw | Cromlech Court | | 59 | 802569E0 | 665F80 | 66C900 | level59.raw | Lizard Island | ===== Level Header ===== The level header is 0xC8 bytes long. Immediately following the level header at offset 0xC8 is the display data loaded into segment 8. A pointer to this display list is also stored at 0x80364458. ^ Offset ^ Size ^ Type ^ Description ^ | 0x00 | 2 | unsigned | TODO stored to 0x803BE714, stored to (*0x803C2B88)->h4, passed through s4 | | 0x02 | 2 | unsigned | TODO stored to 0x803BE716, stored to (*0x803C2B88)->h6 | | 0x04 | 2 | unsigned | TODO << 5, stored to word 0x803BE70C, passed through s7 | | 0x06 | 2 | unsigned | TODO << 5, stored to word 0x803BE710, passed through t8 | | 0x08 | 2 | unsigned | TODO stored to 0x803BE720 | | 0x0A | 2 | unsigned | TODO stored to 0x803BE722, handled in proc_802A4464 | | 0x0C | 2 | unsigned | TODO << 5, stored to word 0x803BE718 | | 0x0E | 2 | unsigned | TODO << 5, stored to word 0x803BE71C | | 0x10 | 2 | unsigned | TODO stored to 0x803BE72C, handled in proc_802A3D54, proc_802A3DF8 | | 0x12 | 2 | unsigned | TODO stored to 0x803BE72E, handled in proc_802A3D54, proc_802A3DF8 | | 0x14 | 2 | unsigned | TODO << 5, stored to word 0x803BE724 | | 0x16 | 2 | unsigned | TODO << 5, stored to word 0x803BE728 | | 0x18 | 4 | signed | gravity related (-4 normal, -2 planets), converted to float stored in 0x803EBBF0 | | 0x1C | 4 | unsigned | (1: normal, 0: dip, level18, level20, level34, level43, level9), stored to byte 0x803BE739 | | 0x20 | 4 | unsigned | Ammo boxes (Ballista and Sideswipe) | | 0x24 | 4 | unsigned | Y Collision | | 0x28 | 4 | unsigned | Communication Point | | 0x2C | 4 | unsigned | Animated textures (water, lava, barricades) | | 0x30 | 4 | unsigned | Terrain | | 0x34 | 4 | unsigned | RDUs | | 0x38 | 4 | unsigned | TNT crates | | 0x3C | 4 | unsigned | Square blocks and holes | | 0x40 | 4 | unsigned | Bounding boxes? | | 0x44 | 4 | unsigned | Bounding boxes? | | 0x48 | 4 | unsigned | TODO | | 0x4C | 4 | unsigned | Level bounds? | | 0x50 | 4 | unsigned | Vehicles | | 0x54 | 4 | unsigned | Missile carrier settings | | 0x58 | 4 | unsigned | Unused? (only in lagp and level26) | | 0x5C | 4 | unsigned | Buildings | | 0x60 | 4 | unsigned | Unused (only in chimp and lagp) | | 0x64 | 4 | unsigned | X/Z Collision (prevent walking over ledge) | | 0x68 | 4 | unsigned | Train platform and stopping zones | | 0x6C | 4 | unsigned | X/Z Collision (level perimeter, trees, walls) | | 0x70 | 4 | unsigned | X/Z Player collision | | 0x74 | 4 | unsigned | TODO | | 0x78 | 4 | unsigned | TODO | | 0x7C | 4 | TODO | TODO | | 0x80 | 4 | TODO | TODO | | 0x84 | 4 | TODO | TODO | | 0x88 | 4 | TODO | TODO | | 0x8C | 4 | TODO | TODO | | 0x90 | 4 | unsigned | handled in proc_802A1C88 offset to F3D DL | | 0x94 | 4 | unsigned | handled in proc_802A1C88 offset to F3D DL | | 0x98 | 4 | unsigned | handled in proc_802A1C88 offset to F3D DL | | 0x9C | 4 | unsigned | handled in proc_802A1C88 offset to F3D DL | | 0xA0 | 4 | TODO | TODO | | 0xA4 | 4 | TODO | TODO | | 0xA8 | 4 | TODO | TODO | | 0xAC | 4 | TODO | TODO | | 0xB0 | 4 | TODO | TODO | | 0xB4 | 4 | TODO | TODO | | 0xB8 | 4 | TODO | TODO | | 0xBC | 4 | TODO | TODO | | 0xC0 | 4 | TODO | TODO | ===== Level Data ===== ==== 0x20: Ammo ==== Ballista missile and Sideswipe hydraulic boxes [XX XX] [YY YY] [ZZ ZZ] [TT TT] |X,Y,Z | position of box | | T | type of box (0 = Ballista missile, 1 = Sideswipe hydraulic) | Example: Argent Towers / level10: 0AD8 002C 13AB 0000 0AD8 002C 1379 0000 0AA6 002C 1379 0000 ==== 0x24: Y Collision ==== These are additional collision triangles set up to prevent J-Bomb from clipping through structures from above. In levels that contain the J-Bomb, triangles are drawn around the semi, tunnels, and other things it probably shouldn't mess with from above. Also, the large gray area surrounding the crane in Ironstone Mine is defined with these. [X1 X1] [Y1 Y1] [Z1 Z1] [X2 X2] [Y2 Y2] [Z2 Z2] [X3 X3] [Y3 Y3] [Z3 Z3] [?? ??] |X1,Y1,Z1 \\ X2,Y2,Z2 \\ X3,Y3,Z3 | three 3D coordinates that define a triangle | | ? | TODO padding? always 0 | Example Argent Towers / level10: 010420-010470 03EF 0109 119D 0395 0109 119D 0395 0108 12AB 0000 03EF 0109 119D 0395 0108 12AB 03EF 0108 12AB 0000 0675 00DA 12A9 0701 00DA 12FE 06ED 00DA 131F 0000 0675 00DA 12A9 0661 00DA 12CB 06ED 00DA 131F 0000 ==== 0x28: Communication Point ==== [XX XX] [YY YY] [ZZ ZZ] [AA AA] | X,Y,Z | position of communication point | | A | Always 0, if 1 animates spinning dish before touched | Example Argent Towers / level10: 010470-010480 067F 00BA 0C23 0000 0813 00A5 08A0 0000 ==== 0x2C: Animated Textures ==== {[W0 W0 W0 W0] [CC] [B5] [B6] [??] [??] [??] [??] [??] {[TT TT TT TT]}} | W0 | Texture ID used in lookup | | C | count of records to follow (+1) | | B5 | *0x803C3240 = B5 ? *(B5*4+V0+8) : 0x0 | | B6 | stored to 0x803C324A, if not 0, compares 'C' with 'A5' | | ? | TODO | | T | texture index, overwritten with address | further handled by proc_802A1C20() proc_802A0CFC(T6) - some lookup and DMA W0 read by proc_802A50DC at 802A510C proc_802A4E4C -> proc_802A50DC Levels containing 0x2C: * Angel City lagp * Blackridge Works fact * Salvage Warf bonus1 * Argent Towers level10 * Skerries level11 * Ebony Coast level13 * Oyster Harbor level14 * Carrick Point level15 * Havoc District level16 * Marine Quarter level21 * Cooter Creek level22 * Sleek Streets level25 * Obsidian Mile level26 * Corvine Bluff level27 * Sideswipe level28 * Echo Marches level29 * Glander's Ranch level35 * Dagger Pass level36 * Magma Peak level52 * Lizard Island level59 Example Argent Towers / level10: 010480-0104D0 {0000002F 03 00 00 00 00 0A 00 00 {00000614 00000614}} --> converted to 000965C0 000965C0 {00000032 03 00 00 00 00 0A 00 00 {00000615 00000615}} --> converted to 000975C0 000975C0 {00000033 03 00 00 00 00 0A 00 00 {00000616 00000616}} --> converted to 000945C0 000945C0 {00000043 03 00 00 00 00 0A 00 00 {00000617 00000617}} --> converted to 000955C0 000955C0 614,615,616,617 are texture IDs for flashing road barricade Example Magma Peak / level52: 005800-005838 {00000205 03 00 01 00 00 0F 00 00 {00000A82 00000A83}} {00000202 02 00 01 00 00 0E 00 00 {00000A84}} {00000200 03 00 01 00 00 0F 00 00 {00000633 00000634}} A82,A83,A84 is animated magma 633,634 is water animated waves Example Lizard Island / level59: 0092A0-0092C4 {00000201 03 00 01 00 00 0F 00 00 {00000A82 00000A83}} {00000202 02 00 01 00 00 0E 00 00 {00000A85}} A82,A83 is animated magma A85 is glowing rock ==== 0x30: Terrain ==== Two halfwords from 0x08 and 0x0A in the level header are multiplied to get the count of the number of groups in this list. Each group contains multiple triangles and is stored to an array at 0x803BDB10. Triangles are overlapped between groups. [EE EE EE EE] {[X1 X1] [Y1 Y1] [Z1 Z1] [X2 X2] [Y2 Y2] [Z2 Z2] [X3 X3] [Y3 Y3] [Z3 Z3] [AA] [BB]} | E | end offset of this group of triangles | | X1,Y1,Z1 \\ X2,Y2,Z2 \\ X3,Y3,Z3 | triangle vertices for terrain data | | A | Terrain type \\ 01: low traction / dirt \\ 02: high traction, high speed / roads, rails \\ 03: high traction, medium speed / grass \\ 05: slow speed / ponds \\ 67: high traction, high speed / gravel lots (similar to roads?) | | B | TODO byte at offset 0x13 flag? | proc_802A4464() Example Simian Acres / chimp: 010258-01B6B4 000: 000000F4 004: 03FA 00B6 031E 0328 00B2 0332 0332 00C1 064A 03 00 018: 03FA 008C 031E 03FA 008C 0596 052E 008C 058B 03 00 02C: 03FA 00B6 031E 0332 00C1 064A 03FA 00B6 0596 03 00 040: 03FA 008C 031E 03FA 00B6 031E 03FA 008C 0596 02 00 054: 03FA 00B6 031E 03FA 00B6 0596 03FA 008C 0596 02 00 068: 03FA 00B6 031E 0332 00C1 064A 03FA 00B6 0596 03 00 07C: 03FA 008C 031E 03FA 00B6 031E 03FA 008C 0596 02 00 090: 03FA 00B6 031E 03FA 00B6 0596 03FA 008C 0596 02 00 0A4: 0359 008C 01DC 035A 008C 01E1 073F 008C 0579 03 00 0B8: 035A 008C 01E1 052E 008C 058B 073F 008C 0579 03 00 0CC: 053B 0078 014D 0332 008C 018E 073F 008C 0579 03 00 0E0: 0332 008C 018E 0359 008C 01DC 073F 008C 0579 03 00 0F4: 0000029C 0F8: 03FA 008C 031E 03FA 008C 0596 052E 008C 058B 03 00 10C: 0359 008C 01DC 035A 008C 01E1 073F 008C 0579 03 00 120: 035A 008C 01E1 052E 008C 058B 073F 008C 0579 03 00 134: 073F 008C 0579 0723 008C 0237 06DA 008C 014D 03 01 148: 06DA 008C 014D 053B 0078 014D 073F 008C 0579 03 01 15C: 053B 0078 014D 0332 008C 018E 073F 008C 0579 03 00 ... ==== 0x34: RDUs ==== [XX XX] [YY YY] [ZZ ZZ] | X,Y,Z | position of RDU | proc_802A1674() -> proc_8026FBB0(A0, A1) six halfwords copied out to struct array at 801DC508 *0x8036bed8 + (halfword at 0x8036eb90 * 0x88) Example Simian Acres / chimp: 01B6B4-01B90C 07E2 0013 0AC8 07A6 0013 0AC8 07DD 0016 0A4B 07A1 0016 0A4B 079B 0017 09DA ... ==== 0x38: TNT crates ==== [XX XX] [YY YY] [ZZ ZZ] [EE] [TT] [H8 H8] [PP PP] | X,Y,Z | position of TNT crate | | E | texture | | T | explosion timer (~2-2.5s * this value) \\ (T * 60) stored to halfword (T9 + 0x8039B080) | | H8 | TODO halfword stored to (T1 + 0x8039B08A) | | P | power of TNT (also affects blast radius) | proc_8028D4C0(A0, A1) Example Simian Acres / chimp: 01B90C-01B924 08B3 0012 0B78 00 05 0001 0834 097D 0012 0D82 00 05 0001 0834 ==== 0x3C: Square Blocks ==== [NN NN] {[XX XX] [YY YY] [ZZ ZZ] [T1] [T2] (HH HH) {[X1 X1] [Y1 Y1] [Z1 Z1]... [AA] [BB] [CC] [DD]}} | N | number of square blocks in group, stored as word to 0x8039C710 | | X | << 5 stored to 0x8039C550 + 56*SP[1C] | | Y | << 5 stored to 0x8039C554 + 56*SP[1C] | | Z | << 5 stored to 0x8039C558 + 56*SP[1C] | | T1 | if 'T2' is 8, this is type of block, stored to 0x8039C7F8 | | T2 | block = 0/1/2, hole = 8 | | H | TODO if 'T2' is 8, this flag is present (either 1 or 0) | | X1,Y1,Z1 \\ X2,Y2,Z2 \\ X3,Y3,Z3 | if 'T2' is 8, then eight triangles follow | | A,B,C,D | TODO flags? normals? | proc_8028FDA0() Example Argent Towers / level10: 01C41C-01C4E2 [0001] 0A16 00A4 0BB0 00 00 [0001] 0985 00A4 17BF 00 08 0000 09AB 0095 179B 095D 0095 179B 095D 00B3 179B 07 FD 01 00 09AB 00B3 179B 09AB 0095 179B 095D 00B3 179B 07 FD 01 00 09AB 0095 17E9 09AB 0095 179B 09AB 00B3 179B 0B FF 00 00 09AB 00B3 17E9 09AB 0095 17E9 09AB 00B3 179B 0B FF 00 00 095D 0095 179B 095D 0095 17E9 095D 00B3 17E9 0B FE 01 00 095D 00B3 179B 095D 0095 179B 095D 00B3 17E9 0B FE 01 00 095D 0095 17E9 09AB 0095 17E9 09AB 00B3 17E9 07 FD 00 00 095D 00B3 17E9 095D 0095 17E9 09AB 00B3 17E9 07 FD 00 00 ==== 0x40: Bounding Boxes ==== some bounding boxes [X1 X1] [Z1 Z1] [X2 X2] [Z2 Z2] [?? ??] | X1,Z1 | lower X,Z of box | | X2,Z2 | upper X,Z of box | | ? | TODO Y? type? | proc_802A5510() { t2 = *0x803643E0; t3 = *0x803643E8; t1 = a0 + *(a0 + 0x40); t5 = a0 + *(a0 + 0x44); t6 = -1; t2 >>= 5; t3 >>= 5; while (t1 != t5) { t4 = *(u16*)(0 + t1); if (t2 >= t4) { t4 = *(u16*)(2 + t1); if (t3 >= t4) { t4 = *(u16*)(4 + t1); if (t4 >= t2) { t4 = *(u16*)(6 + t1); if (t4 >= t3) { v0 = *(u16*)(8 + t1); if (v0 >= t6) { t6 = v0; } } } } } t1 += 10; } if (at == 0xBB8) { *(u8*)0x80364411 = 1; } else { t1 = *(u16*)(0x80364450); t6 <<= 5; t6 += t1; *(u16*)0x8036444E = t6; *(u8*)0x80364411 = 0; } } Example Simian Acres / chimp: 01B924-01BA14 00D2 041A 1072 1B8A 00A9 07DA 0ABE 096A 0B86 00F9 064A 0ABE 0776 0C4E 00F9 0456 0ABE 051E 0BEA 00F9 07DA 0C4E 083E 0D16 00F9 064A 0CB2 0712 0E42 00F9 0712 0DDE 096A 0EA6 00F9 0776 0D16 083E 0DDE 00F9 07DA 0C4E 08A2 0D16 00F9 05E6 0EA6 06AE 1036 00F9 051E 1036 064A 10FE 00F9 0712 0F6E 08A2 0FD2 00F9 096A 0E42 0A32 0F0A 00F9 09CE 0F6E 0A96 109A 00F9 0906 109A 09CE 1162 00F9 083E 10FE 0906 122A 00F9 0712 1162 07DA 12F2 00F9 08A2 0F6E 096A 1036 00F9 0A32 0DDE 0AFA 0EA6 00F9 0712 109A 083E 10FE 00F9 0712 0FD2 0776 109A 00F9 09CE 0CB2 0A96 0DDE 00F9 0C8A 041A 1072 1B8A 012F 0AFA 041A 0C8A 0C4E 012F ==== 0x44: Bounding Boxes ==== some bounding boxes [X1 X1] [Z1 Z1] [X2 X2] [Z2 Z2] [?? ??] | X1,Z1 | lower X,Z of box | | X2,Z2 | upper X,Z of box | | ? | TODO Y? type? | proc_802A5604() Example Simian Acres / chimp: 01BA14-01BA46 00D2 0AD5 1072 1B8A 0059 01FE 0B22 051E 18CE 0099 051E 128E 0776 18CE 0067 08A2 0CB2 0E1A 18CE 007B 00D2 0305 1072 0AD5 0121 ==== 0x48: TODO ==== some u32s? Example Simian Acres / chimp: 01BA46-01BA8E 000000B6 000000B6 000000D5 000000D5 000000D2 000000EC 000000F2 00000073 00000101 000000F2 000000B6 000000E9 000000B6 000000B6 000000E9 00000000 00000062 00000062 ==== 0x4C: TODO ==== level bounds? two points X1,Z1 and X2,Z2 [X1 X1] [Z1 Z1] [X2 X2] [Z2 Z2] // set in proc_802A2D68() { ... *0x803BE730 = *(0 + t1); *0x803BE734 = *(2 + t1); *0x803BE732 = *(4 + t1); *0x803BE736 = *(6 + t1); ... } // compared in proc_802A8CCC() { if ((t2 >= *0x803BE730 && t2 <= *0x803BE732) && (t3 >= *0x803BE734 && t3 <= *0x803BE736)) { ... } } Example Simian Acres / chimp: 01BA8E 009E 011B 10B9 1FA8 ==== 0x50: Vehicles ==== records 9 bytes each [TT] [XX XX] [YY YY] [ZZ ZZ] [HH HH] | T | vehicle type (see vehicles) | | X,Y,Z | position of vehicle | | H | heading \\ N/+Z: 0x0 \\ W/+X: 0x400 \\ S/-Z: 0x800 \\ E/-X: 0xC00 | proc_802A350C() -> proc_802A396C(T3=id) Example Simian Acres / chimp: 01BA96-01BABA 00 08C0 008C 0801 0000 // player, north 04 08C0 008C 0801 002D // bulldozer, slightly west of north 07 073C 0014 0B01 0400 // train, west 08 0685 0014 0AFC 0400 // hotrod, west ==== 0x54: Missile Carrier ==== Missile carrier settings. proc_802A303C() [SS] [XX XX] [ZZ ZZ] [HH HH] [DD DD] [??] | S| speed | | X,Z | X,Z start position | | H | heading \\ N/+Z: 0x0 \\ W/+X: 0x400 \\ S/-Z: 0x800 \\ E/-X: 0xC00 | | D | distance carrier travel to complete level | | ? | unused? | Example Simian Acres / chimp: 01BABA 1C 07BC 07E2 0000 0BB8 00 ==== 0x58: Unused? ==== 8 bytes of data, only used in two levels, both with same data Angel City / lagp: 0144CC Obsidian Mile / level26: 01201E 0B3F 0101 0581 0000 if read as X,Y,Z coordinates, lower left corner, up high ==== 0x5C: Buildings ==== proc_802A1D54() [XX XX] [YY YY] [ZZ ZZ] [TT TT] [CC] [B9] [BB BB] [SS SS] | X,Y,Z | position of object | | T | type | | C | if 1, increase 'destroyed buildings' counter | | B9 | TODO stored to t4->b6 | | B | behavior \\ 1: vertical \\ 2: circle \\ 3: horizontal \\ 4: follow player \\ 5: rotation 90 | | S | speed (for moving objects) | Simian Acres / chimp: 01BAC4-01BCD8 07E0 0014 0AEA 001E 00 00 0000 0000 07E0 0014 0B1C 001E 00 00 0000 0000 07A7 0014 0AEA 001E 00 00 0000 0000 07A7 0014 0B1C 001E 00 00 0000 0000 06D3 0012 0B8E 0020 00 04 0000 0000 0777 0012 0B1F 0021 00 00 0000 0000 07E1 0012 0CA2 0023 01 03 0000 0000 080D 0012 0C99 0024 00 00 0000 0000 0814 0012 0C78 0025 00 00 0000 0000 0873 0012 0D77 0026 00 00 0000 0000 087B 0012 0C8E 0027 00 00 0000 0000 07A4 0012 0DB5 002A 01 00 0000 0000 0798 0012 0D39 002B 00 00 0000 0000 078F 0012 0E8A 002C 01 04 0000 0000 0724 0014 0ECD 002D 00 00 0000 0000 067B 0013 0E4F 0030 00 00 0000 0000 ... ==== 0x60: Unused? ==== Probably unused. Data in chimp shows 5 points under bridge. Data in lagp looks like zig-zag lamp post pattern. first byte stored to 0x80364a6e, variable length records after that [H0 H0] [H2 H2] [H4 H4] [H6 H6] [B8] [B9] {**} [GG] [HH] | H0 | TODO u16 << 5, stored as word to (0 + t3) | | H2 | TODO u16 << 5, stored as word to (4 + t3) | | H4 | TODO u16 << 5, stored as word to (8 + t3) | | H6 | TODO u16 << 5, stored as word to (C + t3) | | B8 | TODO stored to (0x10 + t3) | | B9 | TODO stored to (0x13 + t3), used as count for next bytes | | * | TODO 'B9' number of bytes, stored to t5 | | G | TODO stored to (0x11 + t3) | | H | TODO stored to (0x14 + t3) | | 1 | stored to (0x12 + t3) | proc_802A2C54() t3 = 0x803BDFD8 t5 = t3 + 0x15 Example Simian Acres / chimp: 01BCD8-01BD24 FF 07B9 003A 083A 002D 01 03 {04 08 FF} 00 96 07D5 0046 083A 002D 01 03 {04 08 FF} 00 96 07F3 0053 083A 002D 01 03 {04 08 FF} 00 96 079B 0046 083A 002D 01 03 {04 08 FF} 00 96 077D 0053 083A 002D 01 03 {04 08 FF} 00 96 ==== 0x64: X/Z Collision Walls ==== Walls to restrict player movement off edges. [B0] [CC] {BN*} [TT] {[X1 X1] [Y1 Y1] [Z1 Z1] [X1 X1] [Y1 Y1] [Z1 Z1] [X1 X1] [Y1 Y1] [Z1 Z1] [HH HH]} | B0 | stored to offset 0xF9 of 0x803BD310 | | C | count of bytes to follow, stored to offset 0x00 of 0x803BD310 | | BN | CC number of bytes | | T | count of triangles to follow | | XYZ,123 | triangle coordinates | | H | TODO: halfword for each triangle | proc_802A3E9C Example Crystal Rift / level9: 01CE87-01CEE1 00 01 C8 02 1271 010E 06D9 11D9 010E 0606 11E5 00C8 0616 0D 95 1271 010E 06D9 11E5 00C8 0616 125B 00C8 06BA 0D 95 00 03 03 04 0E 02 143D 0370 0C3C 146E 0370 0C3C 146E 03D4 0C3C 07 FF 143D 0370 0C3C 146E 03D4 0C3C 143D 03D4 0C3C 07 FF ==== 0x68: Train Platform ==== Train and barge platform and stopping zone. [B0] [B1] [B2] {[X1 X1] [Z1 Z1] [X2 X2] [Z2 Z2] [X3 X3] [Z3 Z3]} [WW WW WW WW] [AA] {[H0 H0] [H2 H2] [H4 H4] [H6 H6] [H8 H8] [HA HA] [HC HC] [HE HE] [HG HG] [HI HI] [BK]} [CC] {[BZ]} | B0 | TODO stored to T3->bC4 | | B1 | if non-zero, skip B2 (TODO: does something else) | | B2 | count of 6 int16s to follow, stored to T3->bC6 | | X1,Z1 \\ X2,Z2 \\ X3,Z3 | valid stopping zone (smiley face): constructed by 'B2' # triangles | | W | TODO stored to T6 | | A | count of records to follow, stored to T3->bC7, handled by proc_802A41B0() | | H0-HI | struct of 10 halfwords and 1 byte (0x15 bytes) ('A' count of these) | | BK | TODO stored to s0, passed through v0 to proc_802A4168 | | C | count of bytes to follow | | BZ | 'C' number of bytes | proc_802A3F80() Example Simian Acres / chimp: 01BD24-01BD9D 07 00 02 {097B 0B0A 09B7 0B0A 09B7 0AF6} {09B7 0AF6 097B 0AF6 097B 0B0A} 0000B5F4 04 {0889 002B 0B1A 0948 002B 0B1A 0948 0011 0B1A 07FE 01} {0889 002B 0B1A 0948 0011 0B1A 0889 0011 0B1A 07FE 02} {0889 0012 0AE8 0948 0012 0AE8 0948 002C 0AE8 07FF 03} {0889 0012 0AE8 0948 002C 0AE8 0889 002C 0AE8 07FF 04} 04 {01} {02} {03} {04} Example Ebony Coast / level13: 026DB7-026EA8 07 00 02 {11CB 1F42 11B7 1F8F 11CA 1F94} {11CA 1F94 11DF 1F47 11CB 1F42} 0000B5F4 04 {11FB 0164 1E65 11CA 0164 1F1D 11CA 0149 1F1D 0B54 01} {11FB 0164 1E65 11CA 0149 1F1D 11FB 0149 1E65 0B54 02} {122B 014A 1E72 11FA 014A 1F2A 11FA 0164 1F2A 0B54 03} {122B 014A 1E72 11FA 0164 1F2A 122B 0164 1E72 0B54 04} 04 {01} {02} {03} {04} 07 00 02 {1692 0D80 1683 0DBA 1696 0DBF} {1696 0DBF 16A6 0D85 1692 0D80} 0000B5F4 04 {16BE 0164 0CA2 168D 0164 0D5A 168D 0149 0D5A 0B54 05} {16BE 0164 0CA2 168D 0149 0D5A 16BE 0149 0CA2 0B54 06} {16EE 014A 0CAF 16BD 014A 0D67 16BD 0164 0D67 0B54 07} {16EE 014A 0CAF 16BD 0164 0D67 16EE 0164 0CAF 0B54 08} 04 {01} {02} {03} {04} ==== 0x6C: X/Z Collision ==== X/Z Collision (level perimeter, trees, walls) Number of entries = t0->h10 * t0->h12 {[EE EE EE EE] {[X1 X1] [Y1 Y1] [Z1 Z1] [X2 X2] [Y2 Y2] [Z2 Z2] [X3 X3] [Y3 Y3] [Z3 Z3] [AA AA] [BB] [CC]}} | E | end offset current collision group | | X1,Y1,Z1 \\ X2,Y2,Z2 \\ X3,Y3,Z3 | triangle vertices for collision data | | A | TODO: stored to 0x4c(T4) in proc_802A41B0 | | B | TODO: passed through T7 to proc_802A41B0 | | C | TODO: stored to T4 | Two halfwords h10 and h12 from level header are multiplied to get the count of the number of groups in this list. Each group contains multiple triangles that consist of three X,Y,Z points a halfword and two bytes. proc_802A3D54() -> proc_802A41B0() Example Simian Acres / chimp: 01BD9D-01E6E3 0000010C 03FA 008C 0596 03FA 00B6 0596 03FA 00B6 07EE 0BFF 00 00 03FA 008C 0596 03FA 00B6 07EE 03FA 008C 07EE 0BFF 00 00 03FA 00F0 0596 03FA 008C 0596 0494 008C 0590 0816 00 00 03FA 00F0 0596 0494 008C 0590 0494 00BE 0590 0816 00 00 0494 008C 0590 052E 008C 058B 0494 00BE 0590 0816 00 00 03FA 00F0 0596 0494 00BE 0590 0494 00F0 0590 0816 00 00 0494 00BE 0590 052E 008C 058B 052E 00F0 058B 0816 00 00 0494 00BE 0590 052E 00F0 058B 0494 00F0 0590 0816 00 00 052E 00F0 058B 052E 008C 058B 05B3 008C 0586 0815 00 00 052E 00F0 058B 05B3 008C 0586 05BB 00F0 0585 0819 00 00 0637 008C 0582 0647 00F0 0580 05BB 00F0 0585 0819 00 00 05B3 008C 0586 0637 008C 0582 05BB 00F0 0585 0815 00 00 000003BA 0B66 0000 0852 0B66 015B 0852 0B66 015B 0596 0BFE 01 00 0B66 0000 0852 0B66 015B 0596 0B66 0000 0596 0BFE 01 00 07D8 003E 0586 0839 008C 056E 0813 00F0 056E 0879 00 00 0813 00F0 056E 0839 008C 056E 08BD 008C 056E 07FF 00 00 0813 00F0 056E 08BD 008C 056E 08B3 00F0 056D 0801 00 00 ... ==== 0x70: Player Collision ==== Number of entries = t0->h10 * t0->h12 {[EE EE EE EE] {[X1 X1] [Y1 Y1] [Z1 Z1] [X2 X2] [Y2 Y2] [Z2 Z2] [X3 X3] [Y3 Y3] [Z3 Z3] [AA AA] [BB] [CC]}} | E | end offset current, added to T1, compared with T5 inner loop | | X1,Y1,Z1 \\ X2,Y2,Z2 \\ X3,Y3,Z3 | triangle vertices for collision data | | A | TODO: stored to 0x4c(T4) in proc_802A41B0 | | B | passed through T7 to proc_802A41B0 | | C | stored to T4 | proc_802A3DF8() Example Argent Towers / level10: 0211B1, count = 3*5 = 15 00000004 00000008 0000000C 00000010 00000098 062F 00CD 0C83 062F 00BB 0C83 062F 00BA 0BD3 0BFF 00 00 062F 00CD 0C83 062F 00BA 0BD3 062F 00CD 0BD3 0BFE 00 00 06DA 00CD 0BD3 06DA 00BA 0BD3 06DA 00BA 0C83 0BFE 01 00 06DA 00CD 0BD3 06DA 00BA 0C83 06DA 00CD 0C83 0BFE 01 00 062F 00CD 0BD3 062F 00BA 0BD3 06DA 00BA 0BD3 07FF 00 00 062F 00CD 0BD3 06DA 00BA 0BD3 06DA 00CD 0BD3 07FF 00 00 0000009C 00000124 0395 0131 119D 0395 0109 119D 03EF 0108 119D 07FF 00 00 0395 0131 119D 03EF 0108 119D 03EF 0131 119D 07FF 00 00 0395 0131 12AB 0395 0109 12AB 0395 0109 119D 0BFF 00 00 0395 0131 12AB 0395 0109 119D 0395 0131 119D 0BFF 00 00 03EF 0131 119D 03EF 0108 119D 03EF 0108 12AB 0BFE 01 00 03EF 0131 119D 03EF 0108 12AB 03EF 0131 12AB 0BFE 01 00 0000030C 062F 00CD 0C83 062F 00BB 0C83 062F 00BA 0BD3 0BFF 00 00 062F 00CD 0C83 062F 00BA 0BD3 062F 00CD 0BD3 0BFE 00 00 06DA 00CD 0C83 06DA 00BA 0C83 062F 00BB 0C83 07FE 01 00 ... ==== 0x74: TODO ==== 0x74 starts at word boundary, so between 0 and 3 bytes of padding may be inserted [NN NN NN NN] {[EE EE] ... [CC CC CC CC] {[H0 H0] [H2 H2] [H4 H4] [H6 H6] [H8 H8] [HA HA] [HC HC] [HE HE] [HG HG] [BI] ...}} | N | number of structs to allocate | | E | if -1, last set | | ... | TODO | | C | number of 0x44 byte structs in this set | | H0-HG | int16 stored in allocated structs through T3 | | BI | u8 stored in allocated struct through T3 | | ... | TODO | proc_802A1A9C() initializes 'N' structs each of length 0x40 Example Simian Acres / chimp: 01E72C-01F420 000001C0 FFFF 08 32 08 5C 07 2B 08 5C 07 2B 08 10 08 32 08 10 00 07 00 00 00 40 00 80 00 C0 01 00 01 40 01 80 FF FF FF FF FF FF 00000030 072B 00BD 0814 072B 00BD 0860 074C 00BA 0814 02 00 F5 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 F5 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 072B 00BD 0860 074C 00BA 0860 074C 00BA 0814 02 00 F5 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 074C 00BA 0860 076C 00B6 0814 074C 00BA 0814 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 074C 00BA 0860 076C 00B6 0860 076C 00B6 0814 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 076C 00B6 0860 078D 00B4 0814 076C 00B6 0814 02 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 ... ==== 0x78: TODO ==== looking at F3D DL for 0xFD G_SETTIMG commands to dynamically load textures Added to offset of start of level, passed as s0/s1 to proc_802A08E4 proc_802A08E4() - records 8 bytes, used as 2 words s3 = *(0x803B8D40); s5 = *(0x803B8D44); do { w0 = read_u32_be(s0); s0 += 8; } while (((w0 & 0xFF000000) >> 24) == 0xFD); w1 = read_u32_be(s0-4); s4 = 0x803B8570; while (w1 != *s4 && s3 != s4) { s4 += 8; } ==== 0x88: TODO ==== Display list stuff, related to 0x2C animated textures calls proc_802A50DC with T4 = ID of W0 to change