Skip to content

Commit

Permalink
Merge pull request pnill#510 from punpckhdq/draw_string
Browse files Browse the repository at this point in the history
draw_string & main_render.cpp hook
  • Loading branch information
nukeulater authored Dec 31, 2023
2 parents c031fa3 + 5a7f2ca commit dc70262
Show file tree
Hide file tree
Showing 15 changed files with 377 additions and 421 deletions.
19 changes: 19 additions & 0 deletions xlive/Blam/Engine/main/main_render.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "stdafx.h"
#include "main_render.h"

#include "Blam/Engine/render/render_cartographer_ingame_ui.h"

#include "Util/Hooks/Hook.h"

void main_render_hook()
{
render_cartographer_status_text();
render_cartographer_achievements();
render_cartographer_update();
}

void main_render_apply_patches()
{
// this is replacing a nullsub
PatchCall(Memory::GetAddress(0x19228E), main_render_hook);
}
3 changes: 3 additions & 0 deletions xlive/Blam/Engine/main/main_render.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

void main_render_apply_patches();
58 changes: 58 additions & 0 deletions xlive/Blam/Engine/math/color_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,61 @@ union real_rgb_color
CHECK_STRUCT_SIZE(real_rgb_color, sizeof(real32) * 3);

const pixel32 global_black_pixel32 = { 255,255,255,255 };

// h1/reach puts these in cseries.obj because it is the first file that includes them? or defines them?
const real_argb_color global_real_argb_color_table[] =
{
{ 1.f, 1.f, 1.f, 1.f },
{ 1.f, .5f, .5f, .5f },
{ 1.f, .0f, .0f, .0f },
{ 1.f, 1.f, .0f, .0f },
{ 1.f, .0f, 1.f, .0f },
{ 1.f, .0f, .0f, 1.f },
{ 1.f, .0f, 1.f, 1.f },
{ 1.f, 1.f, 1.f, .0f },
{ 1.f, 1.f, .0f, 1.f },
{ 1.f, 1.f, .41f, .7f },
{ 1.f, .39f, .58f, .93f },
{ 1.f, 1.f, .5f, .0f },
{ 1.f, .44f, .05f, .43f },
{ 1.f, .5f, 1.f, .83f },
{ 1.f, .0f, .39f, .0f },
{ 1.f, 1.f, .63f, .48f },
{ 1.f, .81f, .13f, .56f }
};

const real_argb_color* const global_real_argb_white = &global_real_argb_color_table[0];
const real_argb_color* const global_real_argb_grey = &global_real_argb_color_table[1];
const real_argb_color* const global_real_argb_black = &global_real_argb_color_table[2];
const real_argb_color* const global_real_argb_red = &global_real_argb_color_table[3];
const real_argb_color* const global_real_argb_green = &global_real_argb_color_table[4];
const real_argb_color* const global_real_argb_blue = &global_real_argb_color_table[5];
const real_argb_color* const global_real_argb_cyan = &global_real_argb_color_table[6];
const real_argb_color* const global_real_argb_yellow = &global_real_argb_color_table[7];
const real_argb_color* const global_real_argb_magenta = &global_real_argb_color_table[8];
const real_argb_color* const global_real_argb_pink = &global_real_argb_color_table[9];
const real_argb_color* const global_real_argb_lightblue = &global_real_argb_color_table[10];
const real_argb_color* const global_real_argb_orange = &global_real_argb_color_table[11];
const real_argb_color* const global_real_argb_purple = &global_real_argb_color_table[12];
const real_argb_color* const global_real_argb_aqua = &global_real_argb_color_table[13];
const real_argb_color* const global_real_argb_darkgreen = &global_real_argb_color_table[14];
const real_argb_color* const global_real_argb_salmon = &global_real_argb_color_table[15];
const real_argb_color* const global_real_argb_violet = &global_real_argb_color_table[16];

const real_rgb_color* const global_real_rgb_white = (const real_rgb_color* const)&global_real_argb_color_table[0].red;
const real_rgb_color* const global_real_rgb_grey = (const real_rgb_color* const)&global_real_argb_color_table[1].red;
const real_rgb_color* const global_real_rgb_black = (const real_rgb_color* const)&global_real_argb_color_table[2].red;
const real_rgb_color* const global_real_rgb_red = (const real_rgb_color* const)&global_real_argb_color_table[3].red;
const real_rgb_color* const global_real_rgb_green = (const real_rgb_color* const)&global_real_argb_color_table[4].red;
const real_rgb_color* const global_real_rgb_blue = (const real_rgb_color* const)&global_real_argb_color_table[5].red;
const real_rgb_color* const global_real_rgb_cyan = (const real_rgb_color* const)&global_real_argb_color_table[6].red;
const real_rgb_color* const global_real_rgb_yellow = (const real_rgb_color* const)&global_real_argb_color_table[7].red;
const real_rgb_color* const global_real_rgb_magenta = (const real_rgb_color* const)&global_real_argb_color_table[8].red;
const real_rgb_color* const global_real_rgb_pink = (const real_rgb_color* const)&global_real_argb_color_table[9].red;
const real_rgb_color* const global_real_rgb_lightblue = (const real_rgb_color* const)&global_real_argb_color_table[10].red;
const real_rgb_color* const global_real_rgb_orange = (const real_rgb_color* const)&global_real_argb_color_table[11].red;
const real_rgb_color* const global_real_rgb_purple = (const real_rgb_color* const)&global_real_argb_color_table[12].red;
const real_rgb_color* const global_real_rgb_aqua = (const real_rgb_color* const)&global_real_argb_color_table[13].red;
const real_rgb_color* const global_real_rgb_darkgreen = (const real_rgb_color* const)&global_real_argb_color_table[14].red;
const real_rgb_color* const global_real_rgb_salmon = (const real_rgb_color* const)&global_real_argb_color_table[15].red;
const real_rgb_color* const global_real_rgb_violet = (const real_rgb_color* const)&global_real_argb_color_table[16].red;
12 changes: 12 additions & 0 deletions xlive/Blam/Engine/rasterizer/rasterizer_globals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "stdafx.h"
#include "rasterizer_globals.h"

void __cdecl rasterizer_get_screen_bounds(rectangle2d* screen_bounds)
{
INVOKE(0x264ACD, 0, rasterizer_get_screen_bounds, screen_bounds);
}

void __cdecl rasterizer_get_frame_bounds(rectangle2d* frame_bounds)
{
INVOKE(0x264AE3, 0, rasterizer_get_frame_bounds, frame_bounds);
}
5 changes: 5 additions & 0 deletions xlive/Blam/Engine/rasterizer/rasterizer_globals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once
#include "Blam/Engine/math/integer_math.h"

void __cdecl rasterizer_get_screen_bounds(rectangle2d* screen_bounds);
void __cdecl rasterizer_get_frame_bounds(rectangle2d* frame_bounds);
177 changes: 177 additions & 0 deletions xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "render_cartographer_ingame_ui.h"

#include "Blam/Engine/game/game.h"
#include "Blam/Engine/rasterizer/rasterizer_globals.h"
#include "Blam/Engine/shell/shell_windows.h"
#include "Blam/Engine/text/draw_string.h"
#include "Blam/Engine/text/font_cache.h"
#include "Blam/Engine/text/unicode.h"

#include "H2MOD/Modules/Accounts/AccountLogin.h"
#include "H2MOD/Modules/Achievements/Achievements.h"
#include "H2MOD/Modules/Shell/Config.h"

// define this to enable queueing a test message in render_cartographer_achievements
// #define ACHIVEMENT_RENDER_DEBUG_ENABLED

const int32 k_status_text_font = 0;

// defined in XLiveRendering.cpp
extern char* buildText;

void render_cartographer_status_text()
{
rectangle2d bounds;
rasterizer_get_frame_bounds(&bounds);

bool game_is_main_menu = game_is_ui_shell();
bool paused_or_in_menus = *Memory::GetAddress<bool*>(0x47A568) != 0;

wchar_t build_string_buffer[256];
utf8_string_to_wchar_string(buildText, build_string_buffer, NUMBEROF(build_string_buffer));

wchar_t master_state_string_buffer[256];
utf8_string_to_wchar_string(GetMasterStateStr(), master_state_string_buffer, NUMBEROF(master_state_string_buffer));

real_argb_color text_color_console = *global_real_argb_white;
if (game_is_main_menu)
{
text_color_console.alpha = .5f;
}

int32 line_height = get_text_size_from_font_cache(k_status_text_font);
if (game_is_main_menu || (!game_is_main_menu && paused_or_in_menus)) {
draw_string_reset();
draw_string_set_font_and_options(k_status_text_font, 0, 0, 0, &text_color_console, global_real_argb_black, false);

if (H2Config_anti_cheat_enabled)
{
draw_string_set_options(0, 1, 0, false);
draw_string_render(&bounds, L"Anti-cheat is enabled");
draw_string_set_options(0, 0, 0, false);
}

draw_string_render(&bounds, build_string_buffer);
bounds.top += line_height;
draw_string_render(&bounds, master_state_string_buffer);
}
}

const uint64 k_cheevo_display_lifetime = (5 * k_shell_time_msec_denominator);
const uint32 k_cheevo_title_font = 10;
const uint32 k_cheevo_message_font = 1;

void render_cartographer_achievements()
{
static int64 x_cheevo_timer = 0;
int64 time_now = shell_time_now_msec();

#ifdef ACHIVEMENT_RENDER_DEBUG_ENABLED
static bool x_test = false;
if (x_test)
{
AchievementMap.insert({ "Why are we still here? Just to suffer?|I can feel my leg, my arm... even my fingers.", false });
x_test = false;
}
#endif

if (!AchievementMap.empty())
{
// hover over this type to die instantly
auto it = AchievementMap.begin();
if (it->second == false)
{
it->second = true;
x_cheevo_timer = time_now + k_cheevo_display_lifetime;
}

if (x_cheevo_timer - time_now < 0)
{
AchievementMap.erase(it);
}
else
{
rectangle2d bounds;
wchar_t cheevo_message[256];
int32 widget_total_height = get_text_size_from_font_cache(k_cheevo_title_font) + (get_text_size_from_font_cache(k_cheevo_message_font) * 2);
real_argb_color text_color = *global_real_argb_white;
text_color.alpha = (float)(x_cheevo_timer - time_now) / k_cheevo_display_lifetime;

// there should be a better way of doing this instead of every frame!
utf8_string_to_wchar_string(it->first.c_str(), cheevo_message, NUMBEROF(cheevo_message));
wchar_t* divider_position = wcschr(cheevo_message, '|');
if (divider_position)
{
*divider_position = '\0';
}

draw_string_reset();
draw_string_set_font_and_options(k_cheevo_title_font, 0, 2, 0, &text_color, *Memory::GetAddress<real_argb_color**>(0x412780), false);

rasterizer_get_screen_bounds(&bounds);
bounds.top += rectangle2d_height(&bounds) / 3 - (widget_total_height / 2);
draw_string_render(&bounds, L"Achievement Unlocked");
bounds.top += get_text_size_from_font_cache(k_cheevo_title_font);

draw_string_set_font(k_cheevo_message_font);
draw_string_render(&bounds, cheevo_message);
bounds.top += get_text_size_from_font_cache(k_cheevo_message_font);
draw_string_render(&bounds, divider_position ? divider_position + 1 : L"<invalid achievement description>");
}
}
}

// defined in Modules\Updater\Updater.cpp
extern char* autoUpdateText;
extern long long sizeOfDownload;
extern long long sizeOfDownloaded;

const uint32 k_update_status_font = 5;

void render_cartographer_update()
{
if (autoUpdateText)
{
rectangle2d bounds;
wchar_t update_message_buffer[256];
wchar_t* last_line = update_message_buffer;
c_static_wchar_string128 lines[16];
int32 line_count = 0;
int32 update_message_length = 0;

utf8_string_to_wchar_string(autoUpdateText, update_message_buffer, NUMBEROF(update_message_buffer));
update_message_length = ustrnlen(update_message_buffer, NUMBEROF(update_message_buffer));

for (int32 character_index = 0; character_index < NUMBEROF(update_message_buffer) && character_index < update_message_length && line_count < NUMBEROF(lines); character_index++)
{
wchar_t* character = &update_message_buffer[character_index];
if (*character == '\n')
{
*character = '\0';
lines[line_count++].set(last_line);
last_line = &update_message_buffer[character_index + 1];
}
}

draw_string_reset();
draw_string_set_font_and_options(k_update_status_font, 0, 0, 0, global_real_argb_white, global_real_argb_black, false);

rasterizer_get_frame_bounds(&bounds);
bounds.top += rectangle2d_height(&bounds) * .1f;

for (int32 line_index = 0; line_index < line_count; line_index++)
{
draw_string_render(&bounds, lines[line_index].get_string());
bounds.top += get_text_size_from_font_cache(k_update_status_font);
}

if (sizeOfDownload > 0)
{
wchar_t update_message_buffer[256];
float percent_complate = 100.f * ((float)sizeOfDownloaded / sizeOfDownload);
swprintf_s(update_message_buffer, NUMBEROF(update_message_buffer), L"(progress: %.2f%%)", percent_complate);
draw_string_render(&bounds, update_message_buffer);
}
}
}
5 changes: 5 additions & 0 deletions xlive/Blam/Engine/render/render_cartographer_ingame_ui.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

void render_cartographer_status_text();
void render_cartographer_achievements();
void render_cartographer_update();
43 changes: 43 additions & 0 deletions xlive/Blam/Engine/text/draw_string.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "stdafx.h"
#include "draw_string.h"

void __cdecl draw_string_get_color(real_argb_color* color)
{
INVOKE(0x98955, 0, draw_string_get_color, color);
}

void __cdecl draw_string_set_color(real_argb_color const* color)
{
INVOKE(0x98A00, 0, draw_string_set_color, color);
}

void __cdecl draw_string_set_shadow_color(real_argb_color const* color)
{
INVOKE(0x98A38, 0, draw_string_set_shadow_color, color);
}

void __cdecl draw_string_set_font(int32 font_index)
{
INVOKE(0x98A87, 0, draw_string_set_font, font_index);
}

void __cdecl draw_string_set_options(int32 style, int32 justification, uint32 flags, bool wrap_horizontally)
{
INVOKE(0x98A9D, 0, draw_string_set_options, style, justification, flags, wrap_horizontally);
}

void __cdecl draw_string_set_font_and_options(int32 font, int32 style, int32 justification, uint32 flags, real_argb_color const* color, real_argb_color const* shadow_color, bool wrap_horizontally)
{
INVOKE(0x98AC4, 0, draw_string_set_font_and_options, font, style, justification, flags, color, shadow_color, wrap_horizontally);
}

void __cdecl draw_string_reset()
{
INVOKE(0x98CDC, 0, draw_string_reset);
}

// is this in a different file? where should this be
void __cdecl draw_string_render(rectangle2d const* bounds, wchar_t const* string)
{
INVOKE(0x271BC8, 0, draw_string_render, bounds, string);
}
12 changes: 12 additions & 0 deletions xlive/Blam/Engine/text/draw_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include "Blam/Engine/math/color_math.h"
#include "Blam/Engine/math/integer_math.h"

void __cdecl draw_string_get_color(real_argb_color* color);
void __cdecl draw_string_set_color(real_argb_color const* color);
void __cdecl draw_string_set_shadow_color(real_argb_color const* color);
void __cdecl draw_string_set_font(int32 font_index);
void __cdecl draw_string_set_options(int32 style, int32 justification, uint32 flags, bool wrap_horizontally);
void __cdecl draw_string_set_font_and_options(int32 font, int32 style, int32 justification, uint32 flags, real_argb_color const* color, real_argb_color const* shadow_color, bool wrap_horizontally);
void __cdecl draw_string_reset();
void __cdecl draw_string_render(rectangle2d const* bounds, wchar_t const* string);
4 changes: 3 additions & 1 deletion xlive/Blam/Engine/text/font_cache.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

void font_group_apply_hooks();
int __cdecl get_text_size_from_font_cache(int font_cache_index);

void font_group_apply_hooks();
2 changes: 2 additions & 0 deletions xlive/H2MOD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "Blam/Engine/items/weapon_definitions.h"
#include "Blam/Engine/main/loading.h"
#include "Blam/Engine/main/main_game.h"
#include "Blam/Engine/main/main_render.h"
#include "Blam/Engine/Networking/NetworkMessageTypeCollection.h"
#include "Blam/Engine/objects/damage.h"
#include "Blam/Engine/units/bipeds.h"
Expand Down Expand Up @@ -943,6 +944,7 @@ void H2MOD::ApplyHooks() {
camera_apply_patches();
player_control_apply_patches();
rasterizer_fog_apply_patches();
main_render_apply_patches();
effects_apply_patches();
}
else {
Expand Down
Loading

0 comments on commit dc70262

Please sign in to comment.