Skip to main content

rgpre/import/
system_ini.rs

1//! Typed SYSTEM.INI settings in their original engine units.
2use super::ini::{ini_section, required, sections};
3use crate::Result;
4
5/// Engine configuration. Missing or empty settings remain `None`.
6#[derive(Debug, Clone, PartialEq, serde::Serialize)]
7pub struct SystemIni {
8    pub screen: ScreenSettings,
9    pub system: SystemSettings,
10    pub debug: DebugSettings,
11    pub game: GameSettings,
12    pub cyrus: CyrusSettings,
13    pub manager3d: Manager3dSettings,
14    pub xngine: XngineSettings,
15    pub camera: CameraSettings,
16    pub dialog: DialogSettings,
17    pub glide: GlideSettings,
18}
19
20impl SystemIni {
21    /// Parse case-insensitive sections and keys, retaining the first duplicate key.
22    /// Requires `[system]`; unknown fields are ignored and invalid known values fail.
23    pub fn parse(text: &str) -> Result<Self> {
24        let sections = sections(text, "SYSTEM.INI")?;
25        required(&sections, "SYSTEM.INI", "system")?;
26        Ok(Self {
27            screen: ScreenSettings::parse(sections.get("screen"))?,
28            system: SystemSettings::parse(sections.get("system"))?,
29            debug: DebugSettings::parse(sections.get("debug"))?,
30            game: GameSettings::parse(sections.get("game"))?,
31            cyrus: CyrusSettings::parse(sections.get("cyrus"))?,
32            manager3d: Manager3dSettings::parse(sections.get("3dmanager"))?,
33            xngine: XngineSettings::parse(sections.get("xngine"))?,
34            camera: CameraSettings::parse(sections.get("camera"))?,
35            dialog: DialogSettings::parse(sections.get("dialog"))?,
36            glide: GlideSettings::parse(sections.get("3dfx"))?,
37        })
38    }
39}
40
41ini_section! {
42    /// Settings from `[screen]`. Numeric codes retain their stored values.
43    ScreenSettings {
44        candle_mode: i32 => "candle_mode",
45        colour_bits: i32 => "colour_bits",
46        resolution: i32 => "resolution",
47        palette_red: i32 => "palette_red",
48        palette_green: i32 => "palette_green",
49        palette_blue: i32 => "palette_blue",
50        smk_interlace: bool => "smk_interlace",
51    }
52}
53
54ini_section! {
55    /// Settings from `[system]`. Numeric codes retain their stored values.
56    SystemSettings {
57        game_bitmap: String => "game_bitmap",
58        pointers: String => "pointers",
59        system_font: String => "system_font",
60        icon_font: String => "icon_font",
61        gui_font: String => "gui_font",
62        gui_low_font: String => "gui_low_font",
63        animation_drive: String => "animation_drive",
64        back_texture: i32 => "back_texture",
65        volume: i32 => "volume",
66        sound: bool => "sound",
67        fast_sound: bool => "fast_sound",
68        fidelity: i32 => "fidelity",
69        redbook: bool => "redbook",
70        redbook_volume: i32 => "redbook_volume",
71        sound_distance: i32 => "sound_distance",
72        post_collide_height: u32 => "post_collide_height",
73        hpost_collide_height: i32 => "hpost_collide_height",
74        pre_validate: bool => "pre_validate",
75        normal_frame_rate: i32 => "normal_frame_rate",
76        use_smooth_fps: bool => "use_smooth_fps",
77        use_smooth_divisor: bool => "use_smooth_divisor",
78        min_frame_rate: i32 => "min_frame_rate",
79        max_frame_rate: i32 => "max_frame_rate",
80        jump_time: i32 => "jump_time",
81        jump_height: i32 => "jump_height",
82        sphere_object_scale: i32 => "sphere_object_scale",
83        standing_height: i32 => "standing_height",
84        disable_text: bool => "disable_text",
85        disable_debug_text: bool => "disable_debug_text",
86        normal_ink: i32 => "normal_ink",
87        slide_range: i32 => "slide_range",
88        statics_load: bool => "statics_load",
89        flats_load: bool => "flats_load",
90        objects_load: bool => "objects_load",
91        lights_load: bool => "lights_load",
92        ropes_load: bool => "ropes_load",
93        task_system: bool => "task_system",
94        animation_system: bool => "animation_system",
95        floating_point_physics: bool => "floating_point_physics",
96        rtx_filename: String => "rtx_filename",
97        world_ini: String => "world_ini",
98        item_ini: String => "item_ini",
99        start_fade: bool => "start_fade",
100        compass_xco: i32 => "compass_xco",
101        compass_yco: i32 => "compass_yco",
102        candle_xco: i32 => "candle_xco",
103        candle_yco: i32 => "candle_yco",
104        logbook_xco: i32 => "logbook_xco",
105        logbook_yco: i32 => "logbook_yco",
106        pickup_xco: i32 => "pickup_xco",
107        pickup_yco: i32 => "pickup_yco",
108        pickup_text_yco: i32 => "pickup_text_yco",
109        game_xco1: i32 => "game_xco1",
110        game_yco1: i32 => "game_yco1",
111        game_xco2: i32 => "game_xco2",
112        game_yco2: i32 => "game_yco2",
113        lock_windows: bool => "lock_windows",
114        disable_drive_check: bool => "disable_drive_check",
115        disable_cpu_check: bool => "disable_cpu_check",
116        disable_svga_check: bool => "disable_svga_check",
117        report_machine: bool => "report_machine",
118        max_active_objects: i32 => "max_active_objects",
119        max_effects: i32 => "max_effects",
120        max_particles: i32 => "max_particles",
121        max_remap_objects: i32 => "max_remap_objects",
122        disable_effects: bool => "disable_effects",
123    }
124}
125
126ini_section! {
127    /// Settings from `[debug]`. Numeric codes retain their stored values.
128    DebugSettings {
129        final_version: bool => "final_version",
130        enable_logs: bool => "enable_logs",
131        map_log: bool => "map_log",
132        console_error: bool => "console_error",
133        software_interrupt: bool => "software_interrupt",
134        software_break: bool => "software_break",
135        attempt_recover: bool => "attempt_recover",
136        object_log: bool => "object_log",
137        video_log: bool => "video_log",
138        node_marker: bool => "node_marker",
139        task_debug: bool => "task_debug",
140        memory_manager: i32 => "memory_manager",
141        monitor_object: String => "monitor_object",
142        display_masters: bool => "display_masters",
143        display_slaves: bool => "display_slaves",
144        display_edges: bool => "display_edges",
145        ignore_errors: bool => "ignore_errors",
146        disable_family: bool => "disable_family",
147        disable_master_slaves: bool => "disable_master_slaves",
148        disable_slaves: bool => "disable_slaves",
149        family_log: bool => "family_log",
150        script_log: bool => "script_log",
151        show_manager: bool => "show_manager",
152        display_node_map: bool => "display_node_map",
153        display_nodes: bool => "display_nodes",
154        display_markers: bool => "display_markers",
155        network_marker_file: String => "network_marker_file",
156        object_system_log: bool => "object_system_log",
157        convert_static_angles: bool => "convert_static_angles",
158        def_checksum: bool => "def_checksum",
159        render_log: bool => "render_log",
160        idebug: i32 => "idebug",
161        idebug_refresh: bool => "idebug_refresh",
162        memory_monitor: bool => "memory_monitor",
163    }
164}
165
166ini_section! {
167    /// Settings from `[game]`. Numeric codes retain their stored values.
168    GameSettings {
169        fall_bounce_height: i32 => "fall_bounce_height",
170        fall_death_height: i32 => "fall_death_height",
171        fall_hurt_height: i32 => "fall_hurt_height",
172        fall_hurt_zap: i32 => "fall_hurt_zap",
173        slide_hurt_height: i32 => "slide_hurt_height",
174        slide_hurt_zap: i32 => "slide_hurt_zap",
175        rope_jump_add: i32 => "rope_jump_add",
176        rope_attach_angle: i32 => "rope_attach_angle",
177        slide_speed: i32 => "slide_speed",
178        rtx_pickup_override_time: i32 => "rtx_pickup_override_time",
179        swim_depth: i32 => "swim_depth",
180        player_dead_time: i32 => "player_dead_time",
181        player_fall_dead_time: i32 => "player_fall_dead_time",
182        old_combat: bool => "old_combat",
183        lineup_distance: i32 => "lineup_distance",
184        dialog_radius: i32 => "dialog_radius",
185        combat_sphere_scale: i32 => "combat_sphere_scale",
186    }
187}
188
189ini_section! {
190    /// Settings from `[cyrus]`. Numeric codes retain their stored values.
191    CyrusSettings {
192        sheath_sword_delay: i32 => "sheath_sword_delay",
193        auto_defend: bool => "auto_defend",
194        walk_mode: i32 => "walk_mode",
195        turn_speed: u32 => "turn_speed",
196        turn_max_speed: u32 => "turn_max_speed",
197        mouse_turn: bool => "mouse_turn",
198        joy_tolerance: i32 => "joy_tolerance",
199        camera_distance: i32 => "camera_distance",
200        tap_time: i32 => "tap_time",
201        poly_push_units: u32 => "poly_push_units",
202        auto_grab: bool => "auto_grab",
203        smooth_post_min: i32 => "smooth_post_min",
204        smooth_post_max: i32 => "smooth_post_max",
205        smooth_post_divisor: i32 => "smooth_post_divisor",
206    }
207}
208
209ini_section! {
210    /// Settings from `[3dmanager]`. Numeric codes retain their stored values.
211    Manager3dSettings {
212        buffer_kbytes: i32 => "buffer_kbytes",
213        heap_kbytes: i32 => "heap_kbytes",
214        max_objects: i32 => "max_objects",
215        compress: bool => "compress",
216        save_compressed: bool => "save_compressed",
217        cache_objects: bool => "cache_objects",
218        cache_lifetime: i32 => "cache_lifetime",
219        dummy_manager: bool => "dummy_manager",
220        in_view_enabled: bool => "in_view_enabled",
221        shutdown_mode: bool => "shutdown_mode",
222    }
223}
224
225ini_section! {
226    /// Settings from `[xngine]`. Numeric codes retain their stored values.
227    XngineSettings {
228        texture_kbytes: i32 => "texture_kbytes",
229        gfx_kbytes: i32 => "gfx_kbytes",
230        front_plane: i32 => "front_plane",
231        back_plane: i32 => "back_plane",
232        perspective_low_x: i32 => "perspective_low_x",
233        perspective_low_y: i32 => "perspective_low_y",
234        perspective_med_x: i32 => "perspective_med_x",
235        perspective_med_y: i32 => "perspective_med_y",
236        perspective_high_x: i32 => "perspective_high_x",
237        perspective_high_y: i32 => "perspective_high_y",
238        perspective_ultra_x: i32 => "perspective_ultra_x",
239        perspective_ultra_y: i32 => "perspective_ultra_y",
240        detail: i32 => "detail",
241        ambient_light: i32 => "ambient_light",
242        screen_scale: i32 => "screen_scale",
243        haze_depth: i32 => "haze_depth",
244        sky_disable: bool => "sky_disable",
245        sky_move: bool => "sky_move",
246        sky_xrotate: i32 => "sky_xrotate",
247        sky_yrotate: i32 => "sky_yrotate",
248        game_detail: i32 => "game_detail",
249        exclusion: i32 => "exclusion",
250    }
251}
252
253ini_section! {
254    /// Settings from `[camera]`. Numeric codes retain their stored values.
255    CameraSettings {
256        static_rope_threshold: i32 => "static_rope_threshold",
257        obstacle_size: i32 => "obstacle_size",
258        camera_size: i32 => "camera_size",
259        camera_scape_size: i32 => "camera_scape_size",
260        target_offset_x: i32 => "target_offset_x",
261        target_offset_y: i32 => "target_offset_y",
262        target_offset_z: i32 => "target_offset_z",
263        offset_pos_x: i32 => "offset_pos_x",
264        offset_pos_y: i32 => "offset_pos_y",
265        offset_pos_z: i32 => "offset_pos_z",
266        offset_angle_x: i32 => "offset_angle_x",
267        offset_angle_y: i32 => "offset_angle_y",
268        offset_angle_z: i32 => "offset_angle_z",
269        camera_distance: i32 => "camera_distance",
270        camera_min_distance: i32 => "camera_min_distance",
271        camera_right_pos: i32 => "camera_right_pos",
272        camera_left_pos: i32 => "camera_left_pos",
273        camera_combat_angle_offset_x: i32 => "camera_combat_angle_offset_x",
274        camera_combat_angle_offset_y: i32 => "camera_combat_angle_offset_y",
275        camera_combat_angle_offset_z: i32 => "camera_combat_angle_offset_z",
276        camera_combat_distance: i32 => "camera_combat_distance",
277        camera_hang_angle_offset_x: i32 => "camera_hang_angle_offset_x",
278        camera_hang_angle_offset_y: i32 => "camera_hang_angle_offset_y",
279        camera_hang_angle_offset_z: i32 => "camera_hang_angle_offset_z",
280        camera_hang_distance: i32 => "camera_hang_distance",
281        camera_rope_max_vel: i32 => "camera_rope_max_vel",
282        camera_rope_angle_offset_x: i32 => "camera_rope_angle_offset_x",
283        camera_rope_angle_offset_y: i32 => "camera_rope_angle_offset_y",
284        camera_rope_angle_offset_z: i32 => "camera_rope_angle_offset_z",
285        camera_rope_distance: i32 => "camera_rope_distance",
286        camera_rope_above_angle_offset_x: i32 => "camera_rope_above_angle_offset_x",
287        camera_rope_above_angle_offset_y: i32 => "camera_rope_above_angle_offset_y",
288        camera_rope_above_angle_offset_z: i32 => "camera_rope_above_angle_offset_z",
289        camera_rope_above_distance: i32 => "camera_rope_above_distance",
290        camera_rope_above_aim_x: i32 => "camera_rope_above_aim_x",
291        camera_rope_above_aim_y: i32 => "camera_rope_above_aim_y",
292        camera_rope_above_aim_z: i32 => "camera_rope_above_aim_z",
293        camera_rope_below_angle_offset_x: i32 => "camera_rope_below_angle_offset_x",
294        camera_rope_below_angle_offset_y: i32 => "camera_rope_below_angle_offset_y",
295        camera_rope_below_angle_offset_z: i32 => "camera_rope_below_angle_offset_z",
296        camera_rope_below_distance: i32 => "camera_rope_below_distance",
297        camera_rope_below_aim_x: i32 => "camera_rope_below_aim_x",
298        camera_rope_below_aim_y: i32 => "camera_rope_below_aim_y",
299        camera_rope_below_aim_z: i32 => "camera_rope_below_aim_z",
300        camera_debug_angle_offset_x: i32 => "camera_debug_angle_offset_x",
301        camera_debug_angle_offset_y: i32 => "camera_debug_angle_offset_y",
302        camera_debug_angle_offset_z: i32 => "camera_debug_angle_offset_z",
303        camera_debug_distance: i32 => "camera_debug_distance",
304        max_x_angle: i32 => "max_x_angle",
305        min_x_angle: i32 => "min_x_angle",
306        max_vel: i32 => "max_vel",
307        max_y_vel: i32 => "max_y_vel",
308        max_acc: i32 => "max_acc",
309        player_control_x_inc: i32 => "player_control_x_inc",
310        player_control_y_inc: i32 => "player_control_y_inc",
311        glide_x: f32 => "glide_x",
312        glide_y: f32 => "glide_y",
313        glide_z: f32 => "glide_z",
314        glide_angle_x: f32 => "glide_angle_x",
315        glide_angle_y: f32 => "glide_angle_y",
316        glide_angle_z: f32 => "glide_angle_z",
317        cam_prox_up: f32 => "cam_prox_up",
318    }
319}
320
321ini_section! {
322    /// Settings from `[dialog]`. Numeric codes retain their stored values.
323    DialogSettings {
324        menu_start_x: i32 => "menu_start_x",
325        menu_start_y: i32 => "menu_start_y",
326        dialog_max_menu_items: i32 => "dialog_max_menu_items",
327        dialog_max_dialog_lines: i32 => "dialog_max_dialog_lines",
328        dialog_max_text_width: i32 => "dialog_max_text_width",
329        dialog_print_text: bool => "dialog_print_text",
330        dialog_use_speech: bool => "dialog_use_speech",
331        dialog_max_distance: i32 => "dialog_max_distance",
332        menu_traverse_delay: i32 => "menu_traverse_delay",
333    }
334}
335
336ini_section! {
337    /// Settings from `[3dfx]`. Numeric codes retain their stored values.
338    GlideSettings {
339        resolution: i32 => "resolution",
340        text_scale: [i32; 2] => "text_scale",
341        anim_text_scale: [i32; 2] => "anim_text_scale",
342        font_sel: [i32; 2] => "font_sel",
343        font_norm: [i32; 2] => "font_norm",
344        font_used: [i32; 2] => "font_used",
345    }
346}