commit 650aee9015bc4b3835b36c665d2d1a1b23e067ea Author: Jarrod Doyle Date: Sun Jul 14 16:33:00 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81a860e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/test_data diff --git a/DarkFormat.hexproj b/DarkFormat.hexproj new file mode 100644 index 0000000..28ed925 Binary files /dev/null and b/DarkFormat.hexproj differ diff --git a/patterns/Common.hexpat b/patterns/Common.hexpat new file mode 100644 index 0000000..39be3fd --- /dev/null +++ b/patterns/Common.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct Table { + s32 size; + T data; +}; \ No newline at end of file diff --git a/patterns/CowFile.hexpat b/patterns/CowFile.hexpat new file mode 100644 index 0000000..858e83e --- /dev/null +++ b/patterns/CowFile.hexpat @@ -0,0 +1,100 @@ +#include +#include + +#include "FileBase.hexpat" +#include "lgtypes.hexpat" + +#include "chunks/AI_ROOM_DB.hexpat" +#include "chunks/AIACS.hexpat" +#include "chunks/AICONVERSE.hexpat" +#include "chunks/AICRTSZ.hexpat" +#include "chunks/AIGPTHVAR.hexpat" +#include "chunks/AIHearStat.hexpat" +#include "chunks/AIPATHVAR.hexpat" +#include "chunks/AISNDTWK.hexpat" +#include "chunks/AMBIENT.hexpat" +#include "chunks/BASH.hexpat" +#include "chunks/BRHEAD.hexpat" +#include "chunks/BRLIST.hexpat" +#include "chunks/BRVER.hexpat" +#include "chunks/CELL_MOTION.hexpat" +#include "chunks/CELOBJVAR.hexpat" +#include "chunks/CLOUDOBJVAR.hexpat" +#include "chunks/DARKCOMBAT.hexpat" +#include "chunks/DARKMISS.hexpat" +#include "chunks/DISTOBJVAR.hexpat" +#include "chunks/DRKSET.hexpat" +#include "chunks/ENVMAPVAR.hexpat" +#include "chunks/FAMILY.hexpat" +#include "chunks/FILE_TYPE.hexpat" +#include "chunks/FLOW_TEX.hexpat" +#include "chunks/FOGZONEVAR.hexpat" +#include "chunks/MAPISRC.hexpat" +#include "chunks/Mission_GameSysEAX.hexpat" +#include "chunks/RENDPARAMS.hexpat" +#include "chunks/ROOM_DB.hexpat" +#include "chunks/ROOM_EAX.hexpat" +#include "chunks/ScrModules.hexpat" +#include "chunks/SKYMODE.hexpat" +#include "chunks/SKYOBJVAR.hexpat" +#include "chunks/SONGPARAMS.hexpat" +#include "chunks/STAROBJVAR.hexpat" +#include "chunks/TILIST.hexpat" +#include "chunks/TXLIST.hexpat" +#include "chunks/TXTPAT_DB.hexpat" +#include "chunks/WATERBANKS.hexpat" +#include "chunks/WEATHERVAR.hexpat" +#include "chunks/WREXT.hexpat" + +FileHeader file_header @ 0x0; +TableOfContents toc @ file_header.toc_offset; + +TOCEntry brlist_toc = get_toc_entry(toc, "BRLIST"); +TOCEntry scrmodules_toc = get_toc_entry(toc, "ScrModules"); + +Chunk ai_room_db @ get_offset(toc, "AI_ROOM_DB"); +Chunk ai_acuity_sets @ get_offset(toc, "AIACS"); +Chunk ai_conversations @ get_offset(toc, "AICONVERSE"); +Chunk ai_creature_sizes @ get_offset(toc, "AICRTSZ"); +Chunk ai_gamesys_path_options @ get_offset(toc, "AIGPTHVAR"); +Chunk ai_hear_stat @ get_offset(toc, "AIHearStat"); +Chunk ai_path_var @ get_offset(toc, "AIPATHVAR"); +Chunk ai_sound_tweaks @ get_offset(toc, "AISNDTWK"); +Chunk ambient @ get_offset(toc, "AMBIENT"); +Chunk bash @ get_offset(toc, "BASH"); +Chunk br_head @ get_offset(toc, "BRHEAD"); +Chunk br_list @ get_offset(toc, "BRLIST"); +Chunk brush_version @ get_offset(toc, "BRVER"); +Chunk cell_motion @ get_offset(toc, "CELL_MOTION"); +Chunk celestial_object_var_1 @ get_offset(toc, "CELOBJVAR1"); +Chunk celestial_object_var_2 @ get_offset(toc, "CELOBJVAR2"); +Chunk celestial_object_var_3 @ get_offset(toc, "CELOBJVAR3"); +Chunk cloud_object_var @ get_offset(toc, "CLOUDOBJVAR"); +Chunk dark_combat @ get_offset(toc, "DARKCOMBAT"); +Chunk dark_miss @ get_offset(toc, "DARKMISS"); +Chunk distant_art_var @ get_offset(toc, "DISTOBJVAR"); +Chunk dark_settings @ get_offset(toc, "DRKSET"); +Chunk env_map_var @ get_offset(toc, "ENVMAPVAR"); +Chunk family @ get_offset(toc, "FAMILY"); +Chunk file_type @ get_offset(toc, "FILE_TYPE"); +Chunk flow_tex @ get_offset(toc, "FLOW_TEX"); +Chunk fog_zone_var @ get_offset(toc, "FOGZONEVAR"); +Chunk gamesys_eax @ get_offset(toc, "GameSysEAX"); +Chunk hot_regions @ get_offset(toc, "HotRegions"); +Chunk map_i_src @ get_offset(toc, "MAPISRC"); +Chunk mission_eax @ get_offset(toc, "MissionEAX"); +Chunk multibrush @ get_offset(toc, "MultiBrush"); +Chunk rend_params @ get_offset(toc, "RENDPARAMS"); +Chunk room_db @ get_offset(toc, "ROOM_DB"); +Chunk room_eax @ get_offset(toc, "ROOM_EAX"); +Chunk script_modules @ get_offset(toc, "ScrModules"); +Chunk sky_mode @ get_offset(toc, "SKYMODE"); +Chunk sky_object_var @ get_offset(toc, "SKYOBJVAR"); +Chunk mision_song_params @ get_offset(toc, "SONGPARAMS"); +Chunk star_object_var @ get_offset(toc, "STAROBJVAR"); +Chunk ti_list @ get_offset(toc, "TILIST"); +Chunk texture_list @ get_offset(toc, "TXLIST"); +Chunk texture_patch_database @ get_offset(toc, "TXTPAT_DB"); +Chunk water_banks @ get_offset(toc, "WATERBANKS"); +Chunk weather_var @ get_offset(toc, "WEATHERVAR"); +Chunk world_rep @ get_offset(toc, "WREXT"); \ No newline at end of file diff --git a/patterns/FileBase.hexpat b/patterns/FileBase.hexpat new file mode 100644 index 0000000..2aaf173 --- /dev/null +++ b/patterns/FileBase.hexpat @@ -0,0 +1,50 @@ +#pragma once + +using TOCEntry; + +struct Version { + u32 major; + u32 minor; +}; + +struct FileHeader { + u32 toc_offset; + Version version; + padding[256]; + u32 deadbeef; +}; + +struct TableOfContents { + u32 item_count; + TOCEntry items[item_count]; +}; + +struct TOCEntry { + char name[12]; + u32 offset; + u32 size; +}; + +struct ChunkHeader { + char name[12]; + Version version; + padding[4]; +}; + +struct Chunk { + ChunkHeader header; + T data; +}; + +fn get_toc_entry(TableOfContents toc, str entry_name) { + for (u32 i = 0, i < toc.item_count, i = i + 1) { + if (std::string::starts_with(toc.items[i].name, entry_name)) { + return toc.items[i]; + } + } +}; + +fn get_offset(TableOfContents toc, str entry_name) { + TOCEntry entry = get_toc_entry(toc, entry_name); + return entry.offset; +}; \ No newline at end of file diff --git a/patterns/chunks/AIACS.hexpat b/patterns/chunks/AIACS.hexpat new file mode 100644 index 0000000..85bfafb --- /dev/null +++ b/patterns/chunks/AIACS.hexpat @@ -0,0 +1,16 @@ +#pragma once + +struct AcuitySet { + float lighting; + float movement; + float exposure; +}; + +struct AiAcuitySets { + AcuitySet normal; + AcuitySet peripheral; + AcuitySet omni; + AcuitySet light_only; + AcuitySet movement_only; + AcuitySet low_light; +}; \ No newline at end of file diff --git a/patterns/chunks/AICONVERSE.hexpat b/patterns/chunks/AICONVERSE.hexpat new file mode 100644 index 0000000..ed9c818 --- /dev/null +++ b/patterns/chunks/AICONVERSE.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct AiConverse { + u32 count; + u32 ids[count]; +}; \ No newline at end of file diff --git a/patterns/chunks/AICRTSZ.hexpat b/patterns/chunks/AICRTSZ.hexpat new file mode 100644 index 0000000..528133e --- /dev/null +++ b/patterns/chunks/AICRTSZ.hexpat @@ -0,0 +1,10 @@ +#pragma once + +struct AiCreatureSize { + float width; + float height; +}; + +struct AiCreatureSizes { + AiCreatureSize sizes[8]; +}; \ No newline at end of file diff --git a/patterns/chunks/AIGPTHVAR.hexpat b/patterns/chunks/AIGPTHVAR.hexpat new file mode 100644 index 0000000..6029b40 --- /dev/null +++ b/patterns/chunks/AIGPTHVAR.hexpat @@ -0,0 +1,5 @@ +#pragma once + +struct AiGamesysPathOptions { + float large_door_size; +}; \ No newline at end of file diff --git a/patterns/chunks/AIHearStat.hexpat b/patterns/chunks/AIHearStat.hexpat new file mode 100644 index 0000000..d281766 --- /dev/null +++ b/patterns/chunks/AIHearStat.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct AiHearStat { + float distance_multipliers[6]; + s32 decibel_additions[6]; +}; \ No newline at end of file diff --git a/patterns/chunks/AIPATHVAR.hexpat b/patterns/chunks/AIPATHVAR.hexpat new file mode 100644 index 0000000..70f9034 --- /dev/null +++ b/patterns/chunks/AIPATHVAR.hexpat @@ -0,0 +1,5 @@ +#pragma once + +struct AiPathVar { + s32 pathable_water; +}; \ No newline at end of file diff --git a/patterns/chunks/AISNDTWK.hexpat b/patterns/chunks/AISNDTWK.hexpat new file mode 100644 index 0000000..38c1e0f --- /dev/null +++ b/patterns/chunks/AISNDTWK.hexpat @@ -0,0 +1,10 @@ +#pragma once + +struct AiSndTwk { + s32 default_untyped_range; + s32 default_inform_range; + s32 default_minor_anomoly_range; + s32 default_major_anomoly_range; + s32 default_non_combat_high_range; + s32 default_combat_range; +}; \ No newline at end of file diff --git a/patterns/chunks/AI_ROOM_DB.hexpat b/patterns/chunks/AI_ROOM_DB.hexpat new file mode 100644 index 0000000..b9d00b4 --- /dev/null +++ b/patterns/chunks/AI_ROOM_DB.hexpat @@ -0,0 +1,50 @@ +#pragma once + +#include "Common.hexpat" +#include "lgtypes.hexpat" + +namespace AiRoomDb { + struct Cell { + s32 size; + u32 cell_ids[size]; + }; + + struct PathEdge { + u32 cell; + u32 vertex_a; + u32 vertex_b; + }; + + struct Path { + s32 path_version; + Vec3 final_destination; // unsure about this type + s32 current_edge; + bool active; + padding[3]; + s32 size; + PathEdge edges[size]; + }; + + struct PortalPath { + u64 cost; + bool has_path; + padding[3]; + if (has_path) { + Path path; + } + }; + + struct ChunkData { + bool database_empty; + padding[3]; + s32 valid_cell_count; + s32 cell_count; + Cell cells[cell_count]; + // Seems like ROOM_PATHS isn't defined :) + if (0) { + Table>> portal_ai_paths; + s32 portal_hint_count; + s32 portal_hints[portal_hint_count]; + } + }; +} \ No newline at end of file diff --git a/patterns/chunks/AMBIENT.hexpat b/patterns/chunks/AMBIENT.hexpat new file mode 100644 index 0000000..e9b3ddf --- /dev/null +++ b/patterns/chunks/AMBIENT.hexpat @@ -0,0 +1,5 @@ +#pragma once + +struct Ambient { + s32 current_env_idx; +}; \ No newline at end of file diff --git a/patterns/chunks/BASH.hexpat b/patterns/chunks/BASH.hexpat new file mode 100644 index 0000000..82d6665 --- /dev/null +++ b/patterns/chunks/BASH.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct Bash { + float threshold; + float coefficient; +}; \ No newline at end of file diff --git a/patterns/chunks/BRHEAD.hexpat b/patterns/chunks/BRHEAD.hexpat new file mode 100644 index 0000000..8bdaeae --- /dev/null +++ b/patterns/chunks/BRHEAD.hexpat @@ -0,0 +1,16 @@ +#pragma once + +struct BrHead { + char user[16]; + char creator[16]; + char fullname[64]; // I don't think this is actually ever used + s32 ambient; + s32 grid_pow2; + s32 brush_pos; + s32 color_state; + s32 vbrush_info; + bool use_grid; + bool hots_state; + padding[2]; + s32 edit_time; // Milliseconds +}; \ No newline at end of file diff --git a/patterns/chunks/BRLIST.hexpat b/patterns/chunks/BRLIST.hexpat new file mode 100644 index 0000000..3eccfdd --- /dev/null +++ b/patterns/chunks/BRLIST.hexpat @@ -0,0 +1,91 @@ +#pragma once + +#include "lgtypes.hexpat" + +using Br; +using Grid; +using TexInfo; +using BrMedia; +using BrType; + +struct BrList { + Br brushes[while($ < brlist_toc.offset + brlist_toc.size)]; +}; + +// Potentially rename fields depending on the media type? +struct Br { + s16 br_id; + s16 timestamp; + BrType primal_id; + s16 tx_id; + BrMedia media; + s8 flags; // potential bitfield + Vec3 pos; // Brush center + Vec3 sz; // Brush extents (dimensions) + Vec3 ang; + s16 cur_face; + Grid grid; + u8 num_faces; + s8 edge; + s8 point; + s8 use_flg; + s8 group_id; + padding[4]; + // We have to do a double cast here because otherwise the s8 for non-terrain brushes is just wrong?? + if (s8(u8(media)) >= 0) { + TexInfo txs[num_faces]; + } +}; + +struct Grid { + float line_spacing; + Vec3 phase_shift; + Vec3 orientation; + bool grid_enabled; +}; + +struct TexInfo { + s16 id; + u16 rot; + s16 scale; + u16 x; + u16 y; +}; + +enum BrMedia : s8 { + Room = 0xFB, + Flow = 0xFC, + Object = 0xFD, + Area = 0xFE, + Light = 0xFF, + FillSolid = 0x00, + FillAir = 0x01, + FillWater = 0x02, + Flood = 0x03, + Evaporate = 0x04, + SolidToWater = 0x05, + SolidToAir = 0x06, + AirToSolid = 0x07, + WaterToSolid = 0x08, + Blockable = 0x09, +}; + +enum BrPrimType : u8 { + Special = 0x0, + Cylinder = 0x1, + Pyramid = 0x2, + CornerPyr = 0x3, +}; + +enum BrAligned : u8 { + Vertex = 0x0, + Side = 0x1, +}; + +// If we're a "special" brush side_info says what type we are, otherwise it's +// side count - 3 +bitfield BrType { + side_info: 8; + side_aligned: 1; + BrPrimType prim_type: 23; +}; diff --git a/patterns/chunks/BRVER.hexpat b/patterns/chunks/BRVER.hexpat new file mode 100644 index 0000000..8ee6d77 --- /dev/null +++ b/patterns/chunks/BRVER.hexpat @@ -0,0 +1,5 @@ +#pragma once + +struct BrushVersion { + s32 version; +}; \ No newline at end of file diff --git a/patterns/chunks/CELL_MOTION.hexpat b/patterns/chunks/CELL_MOTION.hexpat new file mode 100644 index 0000000..01732e9 --- /dev/null +++ b/patterns/chunks/CELL_MOTION.hexpat @@ -0,0 +1,24 @@ +#pragma once + +#include "lgtypes.hexpat" + +struct CellMotionPortal { + Vec3 center; + u16 angle; + bool in_motion; + padding[3]; + u8 major_axis; + padding[2]; +}; + +struct CellMotionMedium { + Vec3 center; + u16 angle_change; +}; + +struct CellMotion { + CellMotionPortal portal_motions[256]; + CellMotionMedium medium_motions[256]; + s32 unknown; +}; + diff --git a/patterns/chunks/CELOBJVAR.hexpat b/patterns/chunks/CELOBJVAR.hexpat new file mode 100644 index 0000000..ec0173d --- /dev/null +++ b/patterns/chunks/CELOBJVAR.hexpat @@ -0,0 +1,18 @@ +#pragma once + +struct CelObjVar { + bool enable_object; + padding[3]; + bool enable_fog; + padding[3]; + bool is_alpha_texture; + padding[3]; + char texture[256]; + float alpha; + float celestial_offset; + float angular_size; + float latitude; + float longitude; + float rotation; + Vec3 color; +}; \ No newline at end of file diff --git a/patterns/chunks/CLOUDOBJVAR.hexpat b/patterns/chunks/CLOUDOBJVAR.hexpat new file mode 100644 index 0000000..b898aad --- /dev/null +++ b/patterns/chunks/CLOUDOBJVAR.hexpat @@ -0,0 +1,37 @@ +#pragma once + +#include "lgtypes.hexpat" + +using ColorSettings; + +struct CloudObjVar { + bool enable_cloud_deck; + padding[3]; + bool enable_fog; + padding[3]; + bool is_alpha_texture; + padding[3]; + char texture_path[256]; + float alpha; + float height; + float tile_size; + s32 num_tiles_per_side; + s32 num_sub_tiles; + Vec3 wind_velocity; + Vec3 overall_color; + ColorSettings east; + ColorSettings west; + float east_west_rotation; + s32 sub_tile_alpha_start; + ColorSettings glow; + float glow_latitude; + float glow_longitude; + float glow_angle; + s32 glow_tiles; +}; + +struct ColorSettings { + Vec3 color; + ColorMethod color_method; + float scale; +}; \ No newline at end of file diff --git a/patterns/chunks/DARKCOMBAT.hexpat b/patterns/chunks/DARKCOMBAT.hexpat new file mode 100644 index 0000000..f2c652f --- /dev/null +++ b/patterns/chunks/DARKCOMBAT.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct DarkCombat { + s32 backstab_bonus; + float in_combat_min_distance; +}; \ No newline at end of file diff --git a/patterns/chunks/DARKMISS.hexpat b/patterns/chunks/DARKMISS.hexpat new file mode 100644 index 0000000..4e719b9 --- /dev/null +++ b/patterns/chunks/DARKMISS.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct DarkMiss { + s32 num; + char path[9]; +}; \ No newline at end of file diff --git a/patterns/chunks/DISTOBJVAR.hexpat b/patterns/chunks/DISTOBJVAR.hexpat new file mode 100644 index 0000000..a2711ae --- /dev/null +++ b/patterns/chunks/DISTOBJVAR.hexpat @@ -0,0 +1,17 @@ +#pragma once + +struct DistantArtVar { + bool enable_distant_art; + padding[3]; + bool enable_fog; + padding[3]; + char texture_1[256]; + char texture_2[256]; + Vec3 color; + float distance; + float top_latitude; + float bottom_latitude; + s32 num_panels; + s32 num_texture_panels; + float alpha; +}; \ No newline at end of file diff --git a/patterns/chunks/DRKSET.hexpat b/patterns/chunks/DRKSET.hexpat new file mode 100644 index 0000000..e008649 --- /dev/null +++ b/patterns/chunks/DRKSET.hexpat @@ -0,0 +1,7 @@ +#pragma once + +struct DarkSettings { + bool custom_metaprop_action_targets; + padding[3]; + padding[28]; +}; \ No newline at end of file diff --git a/patterns/chunks/ENVMAPVAR.hexpat b/patterns/chunks/ENVMAPVAR.hexpat new file mode 100644 index 0000000..56af8db --- /dev/null +++ b/patterns/chunks/ENVMAPVAR.hexpat @@ -0,0 +1,11 @@ +#pragma once + +struct EnvMap { + char path[64]; +}; + +struct EnvMapVar { + padding[4]; + EnvMap global; + EnvMap regions[64]; +}; \ No newline at end of file diff --git a/patterns/chunks/FAMILY.hexpat b/patterns/chunks/FAMILY.hexpat new file mode 100644 index 0000000..fbd0308 --- /dev/null +++ b/patterns/chunks/FAMILY.hexpat @@ -0,0 +1,11 @@ +#pragma once + +struct FamilyName { + char name[parent.name_len]; +}; + +struct Family { + u32 name_len; + u32 count; + FamilyName names[count]; +}; diff --git a/patterns/chunks/FILE_TYPE.hexpat b/patterns/chunks/FILE_TYPE.hexpat new file mode 100644 index 0000000..6deb8c5 --- /dev/null +++ b/patterns/chunks/FILE_TYPE.hexpat @@ -0,0 +1,19 @@ +#pragma once + +bitfield FileTypeFlags { + padding: 8; + ObjPartConcrete: 1; + ObjPartAbstract: 1; + ObjPartBriefcase: 1; + ObjPartTerrain: 1; + ObjPartMission: 1; + padding: 3; + Mission: 1; + Map: 1; + GameSys: 1; + padding: 13; +}; + +struct FileType { + FileTypeFlags file_type; +}; diff --git a/patterns/chunks/FLOW_TEX.hexpat b/patterns/chunks/FLOW_TEX.hexpat new file mode 100644 index 0000000..6bac0cf --- /dev/null +++ b/patterns/chunks/FLOW_TEX.hexpat @@ -0,0 +1,12 @@ +#pragma once + +struct MotionSurface { + s16 texture_above; + s16 texture_below; + char texture_name_base[16]; + padding[12]; +}; + +struct FlowTex { + MotionSurface motion_surfaces[256]; +}; \ No newline at end of file diff --git a/patterns/chunks/FOGZONEVAR.hexpat b/patterns/chunks/FOGZONEVAR.hexpat new file mode 100644 index 0000000..98a189d --- /dev/null +++ b/patterns/chunks/FOGZONEVAR.hexpat @@ -0,0 +1,14 @@ +#pragma once + +#include "lgtypes.hexpat" + +struct FogZone { + padding[1]; + Vec3 color; + float dist; +}; + +struct FogZoneVar { + FogZone global; + FogZone regional[8]; +}; \ No newline at end of file diff --git a/patterns/chunks/MAPISRC.hexpat b/patterns/chunks/MAPISRC.hexpat new file mode 100644 index 0000000..f4496d2 --- /dev/null +++ b/patterns/chunks/MAPISRC.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct MapISrc { + s32 source_miss; + float compass_diff; +}; \ No newline at end of file diff --git a/patterns/chunks/Mission_GameSysEAX.hexpat b/patterns/chunks/Mission_GameSysEAX.hexpat new file mode 100644 index 0000000..a0a9489 --- /dev/null +++ b/patterns/chunks/Mission_GameSysEAX.hexpat @@ -0,0 +1,7 @@ +#pragma once + +struct AccousticsProperty { + s32 reverb; + s32 dampening; + s32 height; +}; diff --git a/patterns/chunks/RENDPARAMS.hexpat b/patterns/chunks/RENDPARAMS.hexpat new file mode 100644 index 0000000..343e97f --- /dev/null +++ b/patterns/chunks/RENDPARAMS.hexpat @@ -0,0 +1,27 @@ +#pragma once + +#include "lgtypes.hexpat" + +enum SunlightMode : s32 { + SingleUnshadowed = 0x0, + QuadObjcastShadows = 0x1, + QuadUnshadowed = 0x2, + SingleObjcastShadows = 0x3, +}; + +struct RendParams { + char palette_res[16]; + Vec3 ambient_light; + s32 sunlight; + SunlightMode sunlight_mode; + Vec3 sunlight_direction; + float sunlight_hue; + float sunlight_saturation; + float sunlight_brightness; + padding[24]; + float view_distance; + padding[12]; + Vec3 ambient_light_zones[8]; + float global_ai_vis_bias; + float ambient_zone_ai_vis_biases[8]; +}; diff --git a/patterns/chunks/ROOM_DB.hexpat b/patterns/chunks/ROOM_DB.hexpat new file mode 100644 index 0000000..3ba4ae8 --- /dev/null +++ b/patterns/chunks/ROOM_DB.hexpat @@ -0,0 +1,45 @@ +#pragma once + +#include "lgtypes.hexpat" + +struct RoomPortal { + s32 id; + s32 index; + Plane plane; + s32 edge_plane_count; + Plane edge_planes[edge_plane_count]; + s32 far_room_id; + s32 near_room_id; + Vec3 center; + s32 far_portal_id; +}; + +struct WatchListItem { + s32 count; + s32 watch_values[count]; +}; + +struct PortalDistancesCol { + float distances[parent.portal_count]; +}; + +struct Room { + s32 object_id; + s16 room_id; + Vec3 center; + Plane planes[6]; + s32 portal_count; + RoomPortal portals[portal_count]; + PortalDistancesCol portal_distances[portal_count]; + s32 watch_list_size; + WatchListItem watch_list[watch_list_size]; +}; + +struct RoomDb { + bool has_rooms; + padding[3]; + if (has_rooms) { + s32 count; + Room rooms[count]; + } +}; \ No newline at end of file diff --git a/patterns/chunks/ROOM_EAX.hexpat b/patterns/chunks/ROOM_EAX.hexpat new file mode 100644 index 0000000..7498e7c --- /dev/null +++ b/patterns/chunks/ROOM_EAX.hexpat @@ -0,0 +1,6 @@ +#pragma once + +struct RoomEax { + s32 count; + s32 indices[count]; +}; \ No newline at end of file diff --git a/patterns/chunks/SKYMODE.hexpat b/patterns/chunks/SKYMODE.hexpat new file mode 100644 index 0000000..2b06ad2 --- /dev/null +++ b/patterns/chunks/SKYMODE.hexpat @@ -0,0 +1,10 @@ +#pragma once + +enum SkyRenderingMode : s32 { + Textures = 0x0, + Stars = 0x1, +}; + +struct SkyMode { + SkyRenderingMode mode; +}; \ No newline at end of file diff --git a/patterns/chunks/SKYOBJVAR.hexpat b/patterns/chunks/SKYOBJVAR.hexpat new file mode 100644 index 0000000..19068a2 --- /dev/null +++ b/patterns/chunks/SKYOBJVAR.hexpat @@ -0,0 +1,27 @@ +#pragma once + +#include "lgtypes.hexpat" + +struct SkyObjVar { + bool enable_new_sky; + padding[3]; + bool enable_fog; + padding[3]; + float atmosphere_radius; + float earth_radius; + s32 num_latitude_points; + s32 num_longitude_points; + float horizon_dip_angle; + Vec3 pole_color; + Vec3 degree_45_color; + Vec3 degree_70_color; + Vec3 horizon_color; + Vec3 horizon_dip_color; + Vec3 glow_color; + float glow_latitude; + float glow_longitude; + float glow_angle; + float glow_scale; + ColorMethod glow_method; + float clip_latitude; +}; \ No newline at end of file diff --git a/patterns/chunks/SONGPARAMS.hexpat b/patterns/chunks/SONGPARAMS.hexpat new file mode 100644 index 0000000..8d0c618 --- /dev/null +++ b/patterns/chunks/SONGPARAMS.hexpat @@ -0,0 +1,5 @@ +#pragma once + +struct MissionSongParams { + char song_name[32]; +}; \ No newline at end of file diff --git a/patterns/chunks/STAROBJVAR.hexpat b/patterns/chunks/STAROBJVAR.hexpat new file mode 100644 index 0000000..7520a4d --- /dev/null +++ b/patterns/chunks/STAROBJVAR.hexpat @@ -0,0 +1,12 @@ +#pragma once + +struct StarObjVar { + bool enable_stars; + padding[3]; + bool enable_fog; + padding[3]; + float density; + float star_offset; + float max_intensity; + float global_transparency; +}; \ No newline at end of file diff --git a/patterns/chunks/ScrModules.hexpat b/patterns/chunks/ScrModules.hexpat new file mode 100644 index 0000000..4419b43 --- /dev/null +++ b/patterns/chunks/ScrModules.hexpat @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace ScrModules { + + struct Name { + char name[128]; + }; + + struct ChunkData { + Name names[while($ < scrmodules_toc.offset + scrmodules_toc.size)]; + }; +} \ No newline at end of file diff --git a/patterns/chunks/TILIST.hexpat b/patterns/chunks/TILIST.hexpat new file mode 100644 index 0000000..941d5ae --- /dev/null +++ b/patterns/chunks/TILIST.hexpat @@ -0,0 +1,23 @@ +#pragma once + +enum TiAlignmentMode : s32 { + AlignNorm = 0x0, + AlignBr = 0x1, + AlignExt = 0x2, +}; + +struct TiScale { + s16 fractional; // decimal = fractional / 2^16 + s16 integer; +}; + +struct TiItem { + TiAlignmentMode p1; + TiScale scale_x; + TiScale scale_y; +}; + +struct TiList { + s32 count; + TiItem items[count]; +}; \ No newline at end of file diff --git a/patterns/chunks/TXLIST.hexpat b/patterns/chunks/TXLIST.hexpat new file mode 100644 index 0000000..1fef7f4 --- /dev/null +++ b/patterns/chunks/TXLIST.hexpat @@ -0,0 +1,19 @@ +#pragma once + +struct TextureListToken { + char name[16]; +}; + +struct TextureListData { + char tokens[4]; + char name[15]; + char reserved; +}; + +struct TxList { + s32 block_size; + s32 count; + s32 token_count; + TextureListToken tokens[token_count]; + TextureListData data[count]; +}; \ No newline at end of file diff --git a/patterns/chunks/TXTPAT_DB.hexpat b/patterns/chunks/TXTPAT_DB.hexpat new file mode 100644 index 0000000..284a93b --- /dev/null +++ b/patterns/chunks/TXTPAT_DB.hexpat @@ -0,0 +1,11 @@ +#pragma once + +struct TexturePatch { + s32 key; + s32 value; +}; + +struct TexturePatchDatabase { + s32 count; + TexturePatch patches[count]; +}; \ No newline at end of file diff --git a/patterns/chunks/WATERBANKS.hexpat b/patterns/chunks/WATERBANKS.hexpat new file mode 100644 index 0000000..3cc26cb --- /dev/null +++ b/patterns/chunks/WATERBANKS.hexpat @@ -0,0 +1,11 @@ +#pragma once + +struct RGBA { + Vec3 rgb; + padding[1]; + float a; +}; + +struct WaterBanks { + RGBA banks[4]; +}; \ No newline at end of file diff --git a/patterns/chunks/WEATHERVAR.hexpat b/patterns/chunks/WEATHERVAR.hexpat new file mode 100644 index 0000000..63aa177 --- /dev/null +++ b/patterns/chunks/WEATHERVAR.hexpat @@ -0,0 +1,24 @@ +#pragma once + +enum Precipitation : u32 { + Snow = 0x0, + Rain = 0x1, +}; + +struct WeatherVar { + Precipitation precipitation; + float frequency; + float fall_speed; + float visible_distance; + float render_radius; + float alpha; + float brightness; + float snow_jitter; + float rain_length; + float splash_requency; + float splash_radius; + float splash_height; + float splash_duration; + char texture[32]; + Vec3 wind; +}; \ No newline at end of file diff --git a/patterns/chunks/WREXT.hexpat b/patterns/chunks/WREXT.hexpat new file mode 100644 index 0000000..1b880f4 --- /dev/null +++ b/patterns/chunks/WREXT.hexpat @@ -0,0 +1,245 @@ +#pragma once + +#include +#include +#include +#include +#include "FileBase.hexpat" + +using WrHeader; +using WrCell; +using WrCellHeader; +using WrPoly; +using WrRenderPoly; +using WrPlane; +using WrLightMapInfo; +using WrLightMap; +using WrLightMapLayer; +using WrLightMapDataPixel; +using WrBspTree; +using WrBspTreeNode; +using WrBspTreeCellPlane; +using WrLightTable; +using WrLightTableData; +using WrLightTableAnimLight; +using WrCsgCellTable; +using WrCsgCellBrFaceTable; +using WrCsgCellBspPlaneTable; +using WrCsgCellRefTable; +using WrCsgCellSurfaceRef; + +struct WrExt { + WrHeader header; + WrCell cells[header.cell_count]; + WrBspTree bsp_tree; + padding[header.cell_count]; // This is suspicious. Fog? SEE VFIGS MISSDEEDS!! + WrLightTable lights; + WrCsgCellTable csg_cell_table; +}; + +struct WrExtHeader { + s32 size; + s32 version; + s32 flags; // Need to bitmask this + u32 lightmap_format; + s32 lightmap_scale; +}; + +struct WrHeader { + WrExtHeader ext_header; + u32 data_size; + u32 cell_count; + + u32 major = parent.parent.header.version.major; + u32 minor = parent.parent.header.version.minor; + u32 bytes_per_pixel = 0; + if (major == 0 && minor == 23) { + bytes_per_pixel = 1; + } else if (major == 0 && minor == 24) { + bytes_per_pixel = 2; + } else if (major == 0 && minor == 30) { + if (ext_header.lightmap_format == 0) { + bytes_per_pixel = 2; + } else { + bytes_per_pixel = 4; + } + } +}; + +struct WrCell { + WrCellHeader header; + Vec3 p_vertices[header.vertex_count]; + WrPoly p_polys[header.poly_count]; + WrRenderPoly p_render_polys[header.render_poly_count]; + u32 index_count; + u8 p_index_list[index_count]; + WrPlane p_plane_list[header.plane_count]; + u16 p_anim_lights[header.anim_light_count]; + WrLightMapInfo p_light_list[header.render_poly_count]; + WrLightMap lightmaps[header.render_poly_count]; + s32 light_index_count; + u16 p_light_indices[light_index_count]; +}; + +struct WrCellHeader { + u8 vertex_count; + u8 poly_count; + u8 render_poly_count; + u8 portal_poly_count; + u8 plane_count; + u8 medium; + u8 flags; + s32 portal_vertex_list; + u16 num_v_list; + u8 anim_light_count; + u8 motion_index; + Vec3 sphere_center; + float sphere_radius; +}; + +struct WrPoly { + u8 flags; + u8 vertex_count; + u8 plane_id; + u8 clut_id; + u16 destination; + u8 motion_index; + padding[1]; +}; + +struct WrRenderPoly { + Vec3 tex_u; + Vec3 tex_v; + float base_u; + float base_v; + u16 texture_id; + u16 cached_surface; + float texture_mag; + Vec3 center; +}; + +struct WrPlane { + Vec3 normal; + float distance; +}; + +// TODO: Right now we're assuming a certain LM format because I don't know how to pass +// that info from the WrHeader :) +struct WrLightMapInfo { + s16 base_u; + s16 base_v; + s16 padded_width; + u8 height; + u8 width; + u32 data_ptr; + u32 dynamic_light_ptr; + u32 anim_light_bitmask; +}; + +struct WrLightMap { + s32 i = std::core::array_index(); + + // There seems to be an ImHex bug to work around here. Doing this sets every member of the struct + // to the first value. Accessing it directly rather than using a local variable works. + //WrLightMapInfo info = parent.p_light_list[i]; + u8 width = parent.p_light_list[i].width; + u8 height = parent.p_light_list[i].height; + + u32 count = 1 + std::bit::popcount(parent.p_light_list[i].anim_light_bitmask); + u32 bytes_per_pixel = parent.parent.header.bytes_per_pixel; + WrLightMapLayer layers[count]; +}; + +struct WrLightMapLayer { + WrLightMapDataPixel data[parent.width * parent.height]; +}; + +struct WrLightMapDataPixel { + u8 bytes[parent.parent.bytes_per_pixel]; +}; + +struct WrBspTree { + u32 plane_list_count; + Plane plane_list[plane_list_count]; + u32 bsp_tree_size; + WrBspTreeNode bsp_tree[bsp_tree_size]; +}; + +struct WrBspTreeNode { + s24 parent_index; + u8 flags; + WrBspTreeCellPlane cellplane; + u32 inside_index; + u32 outside_index; +}; + +struct WrBspTreeCellPlane { + s32 cell_id; + s32 plane_id; +}; + +struct WrLightTable { + s32 light_count; + s32 dynamic_light_count; + // Newdark doesn't pad out with non-used lights!! + //WrLightTableData light_data[768]; // Looks like 2016 in newdark? + //WrLightTableData light_this[32]; + WrLightTableData lights[light_count + dynamic_light_count]; + WrLightTableData scratchpad_lights[32]; + + s32 anim_light_count; + WrLightTableAnimLight anim_lights[anim_light_count]; +}; + +struct WrLightTableData { + Vec3 location; + Vec3 direction; + Vec3 colour; // only vec3 in wrrgb and wrext + float inner; + float outer; + float radius; +}; + +struct WrLightTableAnimLight { + u16 cell_index; + u8 pos_in_palette; + padding[1]; +}; + +// TODO: My actual understanding of this is basically none :) +struct WrCsgCellTable { + s32 cell_count; + WrCsgCellBrFaceTable br_faces[cell_count]; + s32 num_brushes; + s32 num_brush_faces[num_brushes]; + WrCsgCellBspPlaneTable bsp_planes[num_brushes]; + s32 ref_counts[num_brushes]; + WrCsgCellRefTable refs[num_brushes]; +}; + +struct WrCsgCellBrFaceTable { + s32 i = std::core::array_index(); + + s32 face_ptr[parent.parent.cells[i].header.render_poly_count]; +}; + +struct WrCsgCellBspPlaneTable { + s32 i = std::core::array_index(); + + DPlane planes[parent.num_brush_faces[i]]; +}; + +struct WrCsgCellRefTable { + s32 i = std::core::array_index(); + + if (parent.ref_counts[i] > 0) { + WrCsgCellSurfaceRef refs[parent.ref_counts[i]]; + } +}; + +struct WrCsgCellSurfaceRef { + s32 cell; + u8 surface; + u8 brush_face; + s16 vertex; +}; \ No newline at end of file diff --git a/patterns/lgtypes.hexpat b/patterns/lgtypes.hexpat new file mode 100644 index 0000000..84a2c1b --- /dev/null +++ b/patterns/lgtypes.hexpat @@ -0,0 +1,55 @@ +#pragma once + +using Vec3; +using NameNum; +using NameNumTag; + +struct Plane { + float x; + float y; + float z; + float d; +}; + +struct DPlane { + double x; + double y; + double z; + double d; +}; + +struct Vec3 { + T x; + T y; + T z; +}; + +struct Vec4 { + T x; + T y; + T z; + T w; +}; + +struct NameNum { + // This header section is actually a tag too, but for namings sake I'll leave it like this + s32 max_names; + s32 sys_name_len; + char sys_name[sys_name_len]; + NameNumTag tags[max_names]; +}; + +struct NameNumTag { + s32 value; + if (value != -1) { + s32 name_len; + if (name_len != -1) { + char name[name_len]; + } + } +}; + +enum ColorMethod : s32 { + Sum = 0x0, + Interpolate = 0x1, +}; \ No newline at end of file