diff --git a/config/parked.json b/config/parked.json index 9b0089b7..01aaedae 100644 --- a/config/parked.json +++ b/config/parked.json @@ -913,25 +913,6 @@ "objdiff_percent": 99.934784 } }, - { - "unit": "source/bitmaps/bitmap_utilities", - "function": "_bitmap_2d_uncompress_from_mipmap", - "class": "instruction-scheduling", - "evidence": "Fuzzy-parked under the current house rule after retaining the correct DXT3 alpha4 block type and DecodeBlockAlpha4 owner-header prototype. HCEA commit 570c83fd9c365dad6f2a3e7041705d5b84c7847c corroborates the 2D decompression topology and semantic private name. Target and candidate have the same 880-byte padded envelope, 297 aligned instructions, and all 49 relocation identities. The only normalized difference is the order of two independent final-loop reloads at +0x33A/+0x33D: January reloads the cached height into EDI before source_mipmap_index into EBX, while VC7 emits the reverse order. A bounded diagnostic confirmed that the donor's erroneous DXT3 alpha3 cast/sizeof spelling does not control this tie; it was rejected in favor of the canonical alpha4 definition. No wrong type, volatile access, barrier, fake dependency, assembly, undefined behavior, or exact-only control flow is retained. Reopen only for authoritative January source/local records or a natural same-compiler scheduling donor.", - "measurements": { - "target": { - "size": 880, - "relocation_count": 49, - "normalized_sha256": "4f4b53aed0db63a496b4c239249e9adaaa70adee056f6e6bc6118dc30dc2b4ab" - }, - "base": { - "size": 880, - "relocation_count": 49, - "normalized_sha256": "0d0264895ee68a288dde6eb4dcbd425500971c01ba59158e1fe21ea4f05b456c" - }, - "objdiff_percent": 99.922264 - } - }, { "unit": "source/render/render_particles", "function": "_render_particles", diff --git a/config/symbols.json b/config/symbols.json index 0e4f68e2..39ffe456 100644 --- a/config/symbols.json +++ b/config/symbols.json @@ -3326,8 +3326,8 @@ { "file_offset": 786464, "flags": 32, "name": "_code_000c0020" }, { "file_offset": 786672, "flags": 32, "name": "_hud_load" }, { "file_offset": 786768, "flags": 32, "name": "_hud_autosave" }, -{ "file_offset": 786992, "flags": 32, "name": "_code_000c0230" }, -{ "file_offset": 787344, "flags": 32, "name": "_code_000c0390" }, +{ "file_offset": 786992, "flags": 32, "name": "_hud_draw_friendly_indicator", "static": true }, +{ "file_offset": 787344, "flags": 32, "name": "_hud_draw_players" }, { "file_offset": 787504, "flags": 32, "name": "_code_000c0430" }, { "file_offset": 788384, "flags": 32, "name": "_hud_draw_screen" }, { "file_offset": 788704, "flags": 32, "name": "_get_return_eip" }, @@ -22040,7 +22040,7 @@ { "file_offset": 3033952, "flags": 0, "name": "_hs_source_files_block" }, { "file_offset": 3034132, "flags": 0, "name": "_hs_syntax_data_definition" }, { "file_offset": 3034148, "flags": 0, "name": "_hs_string_data_definition" }, -{ "file_offset": 3034164, "flags": 0, "name": "_data_002e4c34" }, +{ "file_offset": 3034164, "flags": 0, "name": "_default_string" }, { "file_offset": 3034168, "flags": 0, "name": "_global_hud_anchor_names" }, { "file_offset": 3034188, "flags": 0, "name": "_button_mappings", "static": true }, { "file_offset": 3034204, "flags": 0, "name": "_time_code_time" }, diff --git a/docs/object_matching_logs/hud_obj_small_family_closeout_20260901.md b/docs/object_matching_logs/hud_obj_small_family_closeout_20260901.md new file mode 100644 index 00000000..e1a1d3aa --- /dev/null +++ b/docs/object_matching_logs/hud_obj_small_family_closeout_20260901.md @@ -0,0 +1,111 @@ +# `hud.obj` small-family exact closeout (2026-09-01) + +This pass reconstructs six previously unwritten HUD functions as ordinary, +typed source and makes all six strict COFF matches. `hud.obj` advances from +10/22 to 16/22 exact functions, from 448 to 1,488 strict padded code bytes, +and retains every inherited exact function. No HUD function is parked. + +## Authority and provenance + +- Integration base: `9db5116bd94114dc7a315cd181b944fdf587b3c9`. +- Fresh park-metric correction in the isolated lane: + `bcddc674659d394d7c45474ee14c56db412e1eb0`. +- January target `hud.obj` SHA-256: + `fe352130fe6a915c706e634f7c8e1bc7fc268a7eaa1094ede0549c27ae88756f`. +- Candidate `hud.obj` SHA-256: + `989de9ad2321625af53756f97758b32451b40391cd56a9365595d7298a311f7b`. +- Compiler: the pinned Microsoft VC7/XDK compiler through the normal Ninja + edge and PID-isolated `tools/campaign/gate.py` checks. +- Primary semantic donor: HCEA commit + `570c83fd9c365dad6f2a3e7041705d5b84c7847c`, especially + `hud_initialize_for_new_map.c`, `hud_get_item_string.c`, `hud_load.c`, + `hud_autosave.c`, `hud_draw_friendly_indicator.c`, and + `hud_draw_players.c`. +- Independent control-flow corroboration: Stian Halo commit + `fc11d861865735877d5b8b4c408b1a0c06dde3cf`, whose HUD reconstruction + preserves the natural `hud_get_item_string` call inside `hud_autosave`. +- Marathon commit `ce4fdc63f20f6fa39616a86e717118f4d8bdf25c` + was reviewed for contemporary C-series style and conversion idioms. It has + no direct Halo HUD donor. + +All registered local branches/worktrees and the Pastudan, PUNPCKHDQ, HCEA, +and Stian trees were searched before implementation. No more-complete exact +HUD source existed locally. The PUNPCKHDQ HUD file remained the older +skeleton; Pastudan and Stian supplied compatible semantic/address evidence, +not a January build artifact. + +## Strict result + +| Function | Meaningful bytes | Padded bytes | Relocations | Normalized SHA-256 | +| --- | ---: | ---: | ---: | --- | +| `_hud_initialize_for_new_map` | 119 | 128 | 16 | `738d39e24d9f747b2bfdfd4fb8a9069d1149aecd62eec283d6d088b2fa0d7522` | +| `_hud_get_item_string` | 76 | 80 | 4 | `88279655b02010490e2b9306363a215576b892ae68d6f74deba1c6aadea198fa` | +| `_hud_load` | 84 | 96 | 6 | `8ee25cd45250028e76624da1cf4ca7117f17a8dcb1aa83b4a420e3bd31fd8fe6` | +| `_hud_autosave` | 213 | 224 | 11 | `88e97440a0d4627444bfe405793d4b3bf9df676a446f4396e454972baf31a25b` | +| `_hud_draw_friendly_indicator` | 337 | 352 | 26 | `eca01cb04a23898537bd12e78268cc6c94369cf999adf333915e04eb6ac2d010` | +| `_hud_draw_players` | 149 | 160 | 9 | `9077b15c4b4a6b8b1b2f4940f890f5aaa39de4aad230fd15c23cc987c9d2629d` | +| **Total** | **978** | **1,040** | **72** | | + +The owned four-byte `_default_string` data section is also exact, including +its single relocation to the compiler-owned empty wide-string literal. The +previous address-derived `_data_002e4c34` name is replaced with the +HCEA-authenticated semantic name. + +## Source reconstruction + +The lifecycle path uses the real `hud_globals_definition` field offsets, +typed `hud_globals_definition_get` and Unicode-list access macros, named +interface enums, and owner-header subsystem prototypes. The exact assertion +uses January's attested expression spelling and line number. `hud_load` and +`hud_autosave` select the named loading/checkpoint fields and use the normal +local-player APIs. + +`hud_get_item_string` initializes a semantic fallback pointer and replaces it +only after a valid typed Unicode-list lookup. This is the coherent source +shape that explains January's EDI fallback lifetime; it is not a synthetic +register carrier. `hud_autosave` calls that helper normally. VC7 performs the +same natural inline expansion present in January, preserving the intended TU +inline schedule without a forced-inline directive. + +The teammate-marker pair uses `player_get`, `data_iterator`, `render` camera +and frustum fields, the named multiplayer-HUD interface tag, the bitmap and +texture-cache APIs, project `real`/point/rectangle types, and `PIN`. The two +screen-coordinate conversions use the existing `fast_ftol` C-series helper, +which is the target-supported sparse math-assembly boundary. The private +helper is named `hud_draw_friendly_indicator`, marked static, and naturally +receives its argument in EAX; its public caller is `hud_draw_players`. + +The shared camera projection declaration is isolated in +`render/render_camera_projection.h`. Putting it in the widely included camera +structure header moved the already-exact `render_sky` allocator schedule, so +the narrow owner header preserves both correct prototype ownership and the +January declaration schedule in unrelated translation units. + +## Natural adjacent exact gain + +Placing the missing `bitmap_group_get_bitmap_from_sequence` declaration in +its real owner header naturally resolves the final independent-reload order in +`bitmap_utilities.obj::_bitmap_2d_uncompress_from_mipmap`. That function is +now strict exact at 866 meaningful / 880 padded bytes with all 49 relocation +identities and normalized hash +`4f4b53aed0db63a496b4c239249e9adaaa70adee056f6e6bc6118dc30dc2b4ab`. +Its obsolete park entry is removed. This is a semantic header correction, not +an optimizer-only source variation. + +## Validation + +- Focused gate: `hud.obj` 16 exact / 0 residual / 6 unwritten. +- Focused bitmap gate: `_bitmap_2d_uncompress_from_mipmap` exact. +- Whole-tree verdict replay against the pre-pass build: seven gains and zero + exact-function regressions. +- Full `ninja`: pass; semantic report has zero unit errors. +- `python -m pytest -q`: 255 passed. +- Park validator: 77 active / 0 stale / 0 invalid. +- Strict board after the pass: 278/619 complete objects, + 717,027/1,922,413 padded bytes, and 5,020/8,245 functions. + +The six remaining HUD functions are still unwritten: +`_code_000bf660` (48 padded bytes), `_code_000bf840` (48), +`_code_000bf870` (1,744), `_code_000c0020` (208), +`_code_000c0430` (880), and `_hud_draw_screen` (320). They total 3,248 +padded bytes and were left fail-closed for a later coherent cluster pass. diff --git a/source/bitmaps/bitmap_group.h b/source/bitmaps/bitmap_group.h index 9d5ee26d..5bfa63fe 100644 --- a/source/bitmaps/bitmap_group.h +++ b/source/bitmaps/bitmap_group.h @@ -72,7 +72,12 @@ struct bitmap_group struct tag_block bitmap_data; }; -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/BITMAP_GROUP.C */ + +struct bitmap_data *bitmap_group_get_bitmap_from_sequence( + long bitmap_group_index, + short sequence_index, + short frame_index); /* ---------- globals */ diff --git a/source/interface/hud.c b/source/interface/hud.c index 44ad43b2..2952fea0 100644 --- a/source/interface/hud.c +++ b/source/interface/hud.c @@ -39,9 +39,9 @@ symbols in this file: 000C0150 00e0: _hud_autosave (0000) 000C0230 0160: - _code_000c0230 (0000) + _hud_draw_friendly_indicator (0000) 000C0390 00a0: - _code_000c0390 (0000) + _hud_draw_players (0000) 000C0430 0370: _code_000c0430 (0000) 000C07A0 0140: @@ -67,7 +67,7 @@ symbols in this file: 0026FD18 001a: ??_C@_0BK@NJIPBDGF@?$CFs?5?$CIpress?5WHITE?5to?5use?$CJ?$HMn?$AA@ (0000) 002E4C34 0004: - _data_002e4c34 (0000) + _default_string (0000) 00453AAC 0008: _hud_globals (0000) _hud_scripted_globals (0004) @@ -76,19 +76,32 @@ symbols in this file: /* ---------- headers */ #include "cseries/cseries.h" +#include "bitmaps/bitmap_group.h" +#include "cache/texture_cache.h" #include "game/game_engine.h" #include "game/players.h" +#include "interface/hud.h" #include "interface/hud_messaging.h" #include "interface/hud_unit.h" #include "interface/hud_weapon.h" +#include "interface/interface.h" #include "interface/motion_sensor.h" #include "memory/data.h" +#include "objects/objects.h" +#include "render/render.h" +#include "render/render_camera_projection.h" #include "saved games/game_state.h" +#include "sound/game_sound.h" +#include "text/text_group.h" +#include "units/units.h" /* ---------- constants */ /* ---------- macros */ +#define hud_globals_definition_get(index) \ + ((struct hud_globals_definition *)tag_get('hudg', (index))) + /* ---------- structures */ struct hud_scripted_globals @@ -98,46 +111,38 @@ struct hud_scripted_globals byte reserved2[2]; }; +struct hud_globals_definition +{ + byte reserved000[0x94]; + struct tag_reference hud_item_messages; + byte reserved0A4[0x334]; + short loading_begin_index; + short loading_end_index; + short checkpoint_begin_index; + short checkpoint_end_index; + struct tag_reference checkpoint_sound; +}; + typedef char hud_scripted_globals_size_assert[ sizeof(struct hud_scripted_globals) == 0x4 ? 1 : -1]; typedef char hud_scripted_globals_show_hud_help_text_offset_assert[ offsetof(struct hud_scripted_globals, show_hud_help_text) == 0x1 ? 1 : -1]; +typedef char hud_globals_hud_item_messages_index_offset_assert[ + offsetof(struct hud_globals_definition, hud_item_messages.index) == 0xA0 ? 1 : -1]; +typedef char hud_globals_loading_begin_index_offset_assert[ + offsetof(struct hud_globals_definition, loading_begin_index) == 0x3D8 ? 1 : -1]; +typedef char hud_globals_checkpoint_sound_index_offset_assert[ + offsetof(struct hud_globals_definition, checkpoint_sound.index) == 0x3EC ? 1 : -1]; /* ---------- prototypes */ -void hud_dispose_nav_points_from_old_map( - void); -void hud_dispose_nav_points( - void); -void hud_messaging_initialize( - void); -void hud_initialize_unit_interface( - void); -void hud_initialize_weapon_interface( - void); -void hud_initialize_nav_points( - void); -void hud_update_weapon( - void); -void hud_update_unit( - void); -void hud_update_nav_points( - void); -void hud_messaging_globals_update( - void); -void hud_play_unit_sounds( - struct player_datum const *player, - boolean show_hud); -void hud_add_item_message( - short local_player_index, - long item_definition_index, - short quantity, - char message_offset); - /* ---------- globals */ +extern struct hud_globals_definition *hud_globals; extern struct hud_scripted_globals *hud_scripted_globals; +wchar_t const *default_string = L""; + /* ---------- public code */ void hud_initialize( @@ -170,6 +175,25 @@ void hud_dispose( return; } +void hud_initialize_for_new_map( + void) +{ + csmemset(hud_scripted_globals, 0, sizeof(*hud_scripted_globals)); + hud_scripted_globals->show_hud = TRUE; + match_assert( + "c:\\halo\\SOURCE\\interface\\hud.c", + 113, + interface_get_tag_index(_interface_hud_globals)!=NONE); + hud_globals = hud_globals_definition_get( + interface_get_tag_index(_interface_hud_globals)); + hud_messaging_initialize_for_new_map(); + hud_initialize_unit_interface_for_new_map(); + hud_initialize_weapon_interface_for_new_map(); + hud_initialize_nav_points_for_new_map(); + motion_sensor_initialize_for_new_map(); + return; +} + void hud_dispose_from_old_map( void) { @@ -223,6 +247,27 @@ void hud_update( return; } +wchar_t const *hud_get_item_string( + long string_index) +{ + long string_list_index = hud_globals->hud_item_messages.index; + wchar_t const *string = default_string; + + if (string_list_index != NONE) + { + struct string_list const *string_list = + unicode_string_list_definition_get(string_list_index); + if (string_list && VALID_INDEX(string_index, string_list->strings.count)) + { + string = unicode_string_list_get_string( + string_list_index, + (short)string_index); + } + } + + return string; +} + void hud_picked_up_grenade( short local_player_index, long grenade_definition_index) @@ -288,4 +333,150 @@ void hud_picked_up_powerup( return; } +void hud_load( + boolean load) +{ + short string_index = load + ? hud_globals->loading_begin_index + : hud_globals->loading_end_index; + + scripted_hud_messages_clear(); + if (string_index != NONE) + { + hud_print_message( + local_player_get_next(NONE), + hud_get_item_string(string_index)); + } + + return; +} + +void hud_autosave( + boolean active) +{ + short string_index = active + ? hud_globals->checkpoint_begin_index + : hud_globals->checkpoint_end_index; + short local_player_index; + + scripted_hud_messages_clear(); + if (active && hud_globals->checkpoint_sound.index != NONE) + { + unspatialized_impulse_sound_new( + hud_globals->checkpoint_sound.index, + 1.0f); + } + + if (string_index != NONE) + { + for (local_player_index = 0; + local_player_index < MAXIMUM_LOCAL_PLAYERS; + local_player_index++) + { + if (local_player_get_player_index(local_player_index) != NONE) + { + hud_print_message( + local_player_index, + hud_get_item_string(string_index)); + } + } + } + + return; +} + +static void hud_draw_friendly_indicator( + long player_index) +{ + struct player_datum const *player = player_get(player_index); + real_point3d head_position; + real_point3d view_position; + real_point2d screen_position; + point2d position; + real_rectangle2d clip; + struct bitmap_data *bitmap; + real depth_factor; + real fade; + + unit_get_head_position( + player->unit_index, + &head_position); + head_position.z += 0.30000001f; + matrix4x3_transform_point( + &render.frustum.world_to_view, + &head_position, + &view_position); + if (render_camera_view_to_screen( + &render.camera, + &render.frustum, + &view_position, + &screen_position)) + { + bitmap = bitmap_group_get_bitmap_from_sequence( + interface_get_tag_index(_interface_bitmap_multiplayer_hud), + 0, + 0); + if (_texture_cache_bitmap_get_hardware_format(bitmap, FALSE, TRUE)) + { + position.x = + (short)fast_ftol(screen_position.x) - render.camera.viewport_bounds.x0; + position.y = + (short)fast_ftol(screen_position.y) - render.camera.viewport_bounds.y0; + depth_factor = 1.0f - + ((-view_position.z - render.frustum.z_near) * 100.0f) / + (render.frustum.z_far - render.frustum.z_near); + fade = PIN(depth_factor, 0.075000003f, 1.0f); + clip.x0 = 0.0f; + clip.x1 = 1.0f; + clip.y0 = (1.0f - fade) * 0.5f; + clip.y1 = 1.0f; + interface_draw_bitmap( + bitmap, + &position, + &clip, + 1.0f, + 0.0f, + 1.0f); + } + } + + return; +} + +void hud_draw_players( + void) +{ + long player_index = local_player_get_player_index(render.local_player_index); + long team_index = player_get(player_index)->team_index; + + if (player_index != NONE) + { + long teammate_indices[16]; + long teammate_count = 0; + struct data_iterator iterator; + struct player_datum *player; + long teammate_index; + + data_iterator_new(&iterator, player_data); + while ((player = data_iterator_next(&iterator)) != NULL) + { + if (player_index != iterator.datum_index && + team_index == player->team_index && + player->unit_index != NONE) + { + teammate_indices[teammate_count++] = iterator.datum_index; + } + } + + for (teammate_index = 0; + teammate_index < teammate_count; + teammate_index++) + { + hud_draw_friendly_indicator(teammate_indices[teammate_index]); + } + } + + return; +} + /* ---------- private code */ diff --git a/source/interface/hud.h b/source/interface/hud.h index 4b7a9acf..d30c0cb4 100644 --- a/source/interface/hud.h +++ b/source/interface/hud.h @@ -16,10 +16,28 @@ header included in hcex build. /* ---------- prototypes/HUD.C */ +void hud_initialize_for_new_map( + void); +void hud_initialize_nav_points( + void); +void hud_initialize_nav_points_for_new_map( + void); +void hud_dispose_nav_points_from_old_map( + void); +void hud_dispose_nav_points( + void); +void hud_update_nav_points( + void); + +wchar_t const *hud_get_item_string( + long string_index); + void hud_load( boolean load); void hud_autosave( boolean active); +void hud_draw_players( + void); void hud_picked_up_powerup( short local_player_index, diff --git a/source/interface/hud_messaging.h b/source/interface/hud_messaging.h index 85755d71..012d6a2a 100644 --- a/source/interface/hud_messaging.h +++ b/source/interface/hud_messaging.h @@ -16,10 +16,16 @@ header included in hcex build. /* ---------- prototypes/HUD_MESSAGING.C */ +void hud_messaging_initialize( + void); +void hud_messaging_initialize_for_new_map( + void); void hud_messaging_dispose_from_old_map( void); void hud_messaging_dispose( void); +void hud_messaging_globals_update( + void); void scripted_hud_set_flashing_state( boolean flash); void scripted_hud_set_timer_position( @@ -31,6 +37,11 @@ void scripted_hud_messages_clear( void hud_print_message( short local_player_index, wchar_t const *message); +void hud_add_item_message( + short local_player_index, + long item_definition_index, + short quantity, + char message_offset); /* ---------- globals */ diff --git a/source/interface/hud_unit.h b/source/interface/hud_unit.h index b7a09edd..b4ec3a1b 100644 --- a/source/interface/hud_unit.h +++ b/source/interface/hud_unit.h @@ -2,6 +2,13 @@ #define __HUD_UNIT_H #pragma once +struct player_datum; + +void hud_initialize_unit_interface( + void); +void hud_initialize_unit_interface_for_new_map( + void); + void hud_dispose_unit_interface_from_old_map( void); void hud_dispose_unit_interface( @@ -11,4 +18,10 @@ void hud_fix_unit_data( short old_local_player_index, short new_local_player_index); +void hud_update_unit( + void); +void hud_play_unit_sounds( + struct player_datum const *player, + boolean show_hud); + #endif // __HUD_UNIT_H diff --git a/source/interface/hud_weapon.h b/source/interface/hud_weapon.h index 0e6edc07..c93a54f6 100644 --- a/source/interface/hud_weapon.h +++ b/source/interface/hud_weapon.h @@ -2,6 +2,11 @@ #define __HUD_WEAPON_H #pragma once +void hud_initialize_weapon_interface( + void); +void hud_initialize_weapon_interface_for_new_map( + void); + void hud_dispose_weapon_interface_from_old_map( void); void hud_dispose_weapon_interface( @@ -11,4 +16,7 @@ void hud_fix_weapon_data( short old_local_player_index, short new_local_player_index); +void hud_update_weapon( + void); + #endif // __HUD_WEAPON_H diff --git a/source/interface/interface.h b/source/interface/interface.h index 532b43c2..b37318c8 100644 --- a/source/interface/interface.h +++ b/source/interface/interface.h @@ -35,9 +35,20 @@ enum /* ---------- structures */ +struct bitmap_data; +union point2d; +union real_rectangle2d; + /* ---------- prototypes/INTERFACE.C */ long interface_get_tag_index(short interface_tag_index); +void interface_draw_bitmap( + struct bitmap_data const *bitmap, + union point2d const *point, + union real_rectangle2d const *clip, + real scale, + real theta, + real fade); /* ---------- globals */ diff --git a/source/render/render_camera_projection.h b/source/render/render_camera_projection.h new file mode 100644 index 00000000..30170e16 --- /dev/null +++ b/source/render/render_camera_projection.h @@ -0,0 +1,23 @@ +/* +RENDER_CAMERA_PROJECTION.H + +Narrow projection interface kept separate from the shared camera-structure +header so unrelated translation units retain their January declaration order. +*/ + +#ifndef __RENDER_CAMERA_PROJECTION_H +#define __RENDER_CAMERA_PROJECTION_H +#pragma once + +struct render_camera; +struct render_frustum; +union real_point2d; +union real_point3d; + +boolean render_camera_view_to_screen( + struct render_camera const *camera, + struct render_frustum const *frustum, + union real_point3d const *view_point, + union real_point2d *screen_point); + +#endif // __RENDER_CAMERA_PROJECTION_H diff --git a/source/render/render_cameras.c b/source/render/render_cameras.c index c5ca9858..a8b7cc1d 100644 --- a/source/render/render_cameras.c +++ b/source/render/render_cameras.c @@ -130,6 +130,7 @@ symbols in this file: #include "cseries.h" #include "render/render_cameras.h" +#include "render/render_camera_projection.h" /* ---------- constants */ @@ -137,14 +138,6 @@ symbols in this file: /* ---------- structures */ -/* ---------- prototypes */ - -boolean render_camera_view_to_screen( - const struct render_camera *camera, - const struct render_frustum *frustum, - const real_point3d *view_point, - real_point2d *screen_point); - /* ---------- globals */ /* ---------- public code */