Skip to content

feat(intro): Add short Intro Logo for The Super Hackers team#2267

Open
xezon wants to merge 7 commits into
TheSuperHackers:mainfrom
xezon:xezon/add-new-intro
Open

feat(intro): Add short Intro Logo for The Super Hackers team#2267
xezon wants to merge 7 commits into
TheSuperHackers:mainfrom
xezon:xezon/add-new-intro

Conversation

@xezon

@xezon xezon commented Feb 7, 2026

Copy link
Copy Markdown

Merge with Rebase

This change has 5 commits:

  1. Move intro related code to new file and class
  2. Simplify the intro state machine to make it easier to modify and extend
  3. Remove the non functional copyright string and simplify the EA logo movie code. This also shortens the effective EA logo duration by 3 to 5 seconds.
  4. Remove the superfluous legal page from intro sequence, which would have lasted 4 seconds after Sizzle video but was practically never visible except if the mem pass would have failed (relevant for 2000 era computers). I think the condition was actually meant to be the inverse...
  5. Add new intro screen for The Super Hacker team

Old Intro Sequence

  1. EA Logo, 3 seconds, non skippable
  2. Black Screen, 3-5 seconds (*1), non skippable
  3. Sizzle Video, skippable
  4. Legal Page, 4 seconds, practically never shown
  5. Shell Map load screen

(*1) I did not measure how long the black screen was. According to code somewhere between 3 to 5 seconds.

New Intro Sequence

  1. EA Logo, 3 seconds, non skippable
  2. Black Screen, 800 milliseconds, non skippable
  3. The Super Hackers Logo, 3 seconds, non skippable
  4. Black Screen, 1 second, non skippable
  5. Sizzle Video, skippable
  6. Shell Map load screen
image

TODO

  • Replicate in Generals
  • Add pull id to commit titles
  • Verify each commit compiles individually

@xezon xezon added Art Is art related Enhancement Is new feature or request Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Refactor Edits the code with insignificant behavior changes, is never user facing labels Feb 7, 2026
@greptile-apps

greptile-apps Bot commented Feb 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR refactors the intro sequence into a clean state-machine class (Intro) and adds a new The Super Hackers logo screen between the EA logo movie and the Sizzle video. It also removes the legacy m_afterIntro global flag, the playLogoMovie copyright-hold machinery, and the practically-unreachable legal page.

  • Intro class encapsulates all intro states (EALogoMovie → TheSuperHackersWait → TheSuperHackers → SizzleMovieWait → SizzleMovie → Done) with correct skipping when m_playIntro/m_playSizzle are false; enterNextState() loops to Done when no states are enabled.
  • GameClient now owns the Intro instance, deletes it once isDone() returns true, and exposes a new draw() override wired into W3DDisplay's render loop so the TSH logo screen can draw text and images.
  • The effective EA logo hold is shortened (~3 s instead of 5–8 s), the legal page is dropped, and the overall intro sequence is shortened and better structured.

Confidence Score: 5/5

The change is safe to merge; it replaces a fragile ad-hoc intro sequence with a well-structured state machine and removes dead code.

The state machine correctly reaches IntroState_Done even when no states are enabled, m_intro lifecycle (create in init, delete when done or in destructor) is clean, and the previously-flagged issues (duration overflow, public enterNextState, unhandled start state) have all been resolved. No data corruption or broken contracts were found in the changed paths.

No files require special attention.

Important Files Changed

Filename Overview
Core/GameEngine/Include/GameClient/Intro.h New header for Intro class; uses #pragma once, correct GPL + TheSuperHackers copyright, nullptr throughout, and enterNextState() correctly moved to private.
Core/GameEngine/Source/GameClient/Intro.cpp New implementation of intro state machine; state loop correctly reaches IntroState_Done when no states are enabled, fade-in/out logic is guarded by m_fadeValue bounds, and doAsyncWait(3000) duration is correct.
GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp Replaces ad-hoc intro/sizzle state booleans with the new Intro class; m_intro lifecycle (init/update/delete) is clean and the new draw() override correctly delegates to Intro::draw().
Core/GameEngine/Source/GameClient/Display.cpp Removes playLogoMovie() and all copyright-hold-time fields; stopMovie() and update() are simplified cleanly without any dangling references.
GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp Replaces the dead 'end of video example code' comment with TheGameClient->DRAW() and removes the copyright display string rendering block.

Reviews (12): Last reviewed commit: "fixup! feat(intro): Add short Intro Logo..." | Re-trigger Greptile

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

Comment thread Core/GameEngine/Source/GameClient/Intro.cpp
Comment thread Core/GameEngine/Include/GameClient/Intro.h
Comment thread Core/GameEngine/Source/GameClient/Intro.cpp
@greptile-apps

greptile-apps Bot commented Feb 7, 2026

Copy link
Copy Markdown
Additional Comments (1)

GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp
Intro can block startup

GameClient::update() only shows the shell (TheShell->showShellMap/showShell) after m_intro->isDone(). With the new Intro implementation, if the global flags disable both intro and sizzle (m_playIntro==false and m_playSizzle==false) and m_afterIntro is not pre-set, Intro never reaches Done (see IntroState_Start handling), so the game can get stuck in the intro phase and never show the shell. This previously worked because GameEngine::init() forced m_afterIntro = TRUE when m_playIntro was false.

Fix by making Intro immediately become done when there are no enabled states, or by preserving the old m_afterIntro initialization behavior.

Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp
Line: 514:531

Comment:
**Intro can block startup**

`GameClient::update()` only shows the shell (`TheShell->showShellMap/showShell`) after `m_intro->isDone()`. With the new `Intro` implementation, if the global flags disable both intro and sizzle (`m_playIntro==false` and `m_playSizzle==false`) and `m_afterIntro` is not pre-set, `Intro` never reaches `Done` (see `IntroState_Start` handling), so the game can get stuck in the intro phase and never show the shell. This previously worked because `GameEngine::init()` forced `m_afterIntro = TRUE` when `m_playIntro` was false.

Fix by making `Intro` immediately become done when there are no enabled states, or by preserving the old `m_afterIntro` initialization behavior.

How can I resolve this? If you propose a fix, please make it concise.

@xezon xezon force-pushed the xezon/add-new-intro branch from 999721b to 0f278e6 Compare February 7, 2026 14:15
Comment thread Core/GameEngine/Source/GameClient/Intro.cpp Outdated
@xezon xezon force-pushed the xezon/add-new-intro branch from 0f278e6 to 1a738f7 Compare February 7, 2026 16:19

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread Core/GameEngine/Include/GameClient/Intro.h
Comment thread Core/GameEngine/Source/GameClient/Intro.cpp
@helmutbuhler

Copy link
Copy Markdown

Wouldn't it be more appropriate to show the Superhackers stuff in the credits menu? As is this would imply that the whole game is made by us. I don't think it would be fair to show our names more prominently than the original developers.

@xezon

xezon commented Feb 7, 2026

Copy link
Copy Markdown
Author

Wouldn't it be more appropriate to show the Superhackers stuff in the credits menu? As is this would imply that the whole game is made by us. I don't think it would be fair to show our names more prominently than the original developers.

Maybe remove all user names from this Intro and just show the Team name + url?

We can also clarify "Edited by ..."

@helmutbuhler

Copy link
Copy Markdown

Wouldn't it be more appropriate to show the Superhackers stuff in the credits menu? As is this would imply that the whole game is made by us. I don't think it would be fair to show our names more prominently than the original developers.

Maybe remove all user names from this Intro and just show the Team name + url?

We can also clarify "Edited by ..."

I wouldn't add anything to the intro. I don't think it's necessary to remind the player every time the game starts who made the patch. Maybe just add a tiny note on the shellmap screen below the gamename "patched by Superhackers" or something like that.

It's nice though that the 3-5 seconds black screen is removed here!

@Caball009

Caball009 commented Feb 8, 2026

Copy link
Copy Markdown

I didn't even know what the 'black screen' was when I saw this PR, because I have renamed the files for the EA logo and sizzle and I don't see it. This makes the game launch faster, and saves me 5+ seconds every time I launch the game. I strongly dislike changing anything that would unnecessarily increase the launch time for me as developer. I'm ok with it if I can skip it with some command line.

That said, I like the new intro.

@LegionnaireG

LegionnaireG commented Feb 8, 2026

Copy link
Copy Markdown

I don't think people will understand what it means if the intro screen is this plain. On the intro, maybe add 3 to 5 sentences with the key achievements of TheSuperHackers. Maybe something like:

  We've patched up the game to bring you:
  - Improving game stability
  - Unlocked 60+ FPS for single player
  - Significant reduction in mismatches for multiplayer
  - Higher graphics preset
  - Vulnerability fixes

@tintinhamans

Copy link
Copy Markdown

I don't think people will understand what it means if the intro screen is this plain. On the intro, maybe add 3 to 5 sentences with the key achievements of TheSuperHackers. Maybe something like:

  We've patched up the game to bring you:
  - Improving game stability
  - Unlocked 60+ FPS for single player
  - Significant reduction in mismatches for multiplayer
  - Higher graphics preset
  - Vulnerability fixes

I feel like adding too much text won't really be very useful given the fact that it's only shown for 3 seconds.

@xezon

xezon commented Feb 8, 2026

Copy link
Copy Markdown
Author

I feel like adding too much text won't really be very useful given the fact that it's only shown for 3 seconds.

I agree with this sentiment.

What we can add is a "Improved by" on top, to clarify that this Author has improved the game. This is very simple and broad.

@xezon

xezon commented Feb 9, 2026

Copy link
Copy Markdown
Author

When this is merged I will make a follow up to skip the entire intro sequence with a single ESC press. This will alleviate any waiting pains for impatient users.

@xezon xezon force-pushed the xezon/add-new-intro branch from 1a738f7 to 29b1ce7 Compare February 11, 2026 19:46
@xezon

xezon commented Feb 11, 2026

Copy link
Copy Markdown
Author

Improvements applied according to feedbacks:

  • Removed all individual contributor names (to be shown in Credits Menu instead)
  • Replaced github url with domain name
  • Added pretext to clarify that we did not built the game, but improved it
image

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps

greptile-apps Bot commented Feb 11, 2026

Copy link
Copy Markdown
Additional Comments (1)

GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp
Missing cleanup of m_intro in destructor - potential memory leak if GameClient is destroyed before intro completes.

	delete m_intro;
	m_intro = nullptr;
Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp
Line: 119:119

Comment:
Missing cleanup of `m_intro` in destructor - potential memory leak if `GameClient` is destroyed before intro completes.

```suggestion
	delete m_intro;
	m_intro = nullptr;
```

How can I resolve this? If you propose a fix, please make it concise.

@xezon xezon force-pushed the xezon/add-new-intro branch from 29b1ce7 to 9c82551 Compare February 11, 2026 19:55
@xezon xezon requested a review from tintinhamans February 11, 2026 19:58

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread Core/GameEngine/Source/GameClient/Intro.cpp Outdated
@xezon

xezon commented Feb 11, 2026

Copy link
Copy Markdown
Author

Maybe text can be made a bit bigger.

@fbraz3

fbraz3 commented Feb 13, 2026

Copy link
Copy Markdown

A suggestion: the credits screen would display all contributors names.

Something like:

# TheSuperHackers Team

Name 1 - Role
Name 2 - Role
Name 3 - Role
......

# Individual Contributors

Name 4 - 100 commits
Name 5 - 95 commits
.....

# EA games
......
......
......

The git summary command from Git Extras can be used to generate the individual contributors report and add it dinamically on build time.
https://github.com/tj/git-extras/blob/main/Commands.md#git-summary

@Mauller

Mauller commented Mar 10, 2026

Copy link
Copy Markdown

How about some old school ASCII text? Like the Atari days.

  _______ _             _____                       _    _            _                 
 |__   __| |           / ____|                     | |  | |          | |                
    | |  | |__   ___  | (___  _   _ _ __   ___ _ __| |__| | __ _  ___| | _____ _ __ ___ 
    | |  | '_ \ / _ \  \___ \| | | | '_ \ / _ \ '__|  __  |/ _` |/ __| |/ / _ \ '__/ __|
    | |  | | | |  __/  ____) | |_| | |_) |  __/ |  | |  | | (_| | (__|   <  __/ |  \__ \
    |_|  |_| |_|\___| |_____/ \__,_| .__/ \___|_|  |_|  |_|\__,_|\___|_|\_\___|_|  |___/
                                   | |                                                  
                                   |_|                                                  

@xezon xezon force-pushed the xezon/add-new-intro branch from 832f3d8 to f3a985c Compare March 22, 2026 10:14
@xezon

xezon commented Mar 22, 2026

Copy link
Copy Markdown
Author

How about some old school ASCII text?

Maybe is a bit difficult to read. Also makes it look like hackware.

Rebased.

@xezon xezon requested a review from tintinhamans March 25, 2026 18:44
@DevGeniusCode

Copy link
Copy Markdown

I've checked this locally and it rebases cleanly onto the current main branch with no conflicts. LGTM for merging

(I think the pretext of Game fixed and improved by is better)

Additionally, I wonder if instead of hardcoding this into the game engine, wouldn't it be better to create an external file like the original game intro EA_LOGO.BIK

@xezon

xezon commented Apr 18, 2026

Copy link
Copy Markdown
Author

Game fixed and improved by. I am convinced we cannot claim this. Because "Game fixed" implies that there will be no big bugs in the game: no crashes, no mismatches. As soon as a user has a crash or any other bug, the intro title would be a lie. Game improved by is a much more truthful title for it.

We cannot put a BIK video because it would not work in forks of this project and requires a data patch. The intro is intentionally hard coded, because it is not meant to be changed, other than the localization.

@xezon xezon force-pushed the xezon/add-new-intro branch from f3a985c to bf25fd5 Compare April 18, 2026 17:42
@xezon

xezon commented Apr 18, 2026

Copy link
Copy Markdown
Author

Rebased and ASCII art added for retro look

shot_20260418_194121_2

Comment thread Core/GameEngine/Source/GameClient/Intro.cpp
@DevGeniusCode

DevGeniusCode commented Apr 23, 2026

Copy link
Copy Markdown

Maybe something like "open source community" should be added to attract developers
Maybe replace the website address with the GitHub address.

@xezon

xezon commented May 22, 2026

Copy link
Copy Markdown
Author

Needs rebase and review.

@githubawn

Copy link
Copy Markdown
image image
  1. I don't think ASCII is worth the trouble even though it looks pretty cool.

Maybe something like this:

// logo.h - Generated from logo.png using a tool like xxd or a python script
const unsigned char LOGO_IMAGE_BYTES[] = {
    0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
    // ... thousands of bytes ...
    0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
const unsigned int LOGO_IMAGE_BYTES_LEN = sizeof(LOGO_IMAGE_BYTES);

Embedding an image into the exe is also possible. Some IDE's have resource editors.

// resource.rc
IDB_LOGO_IMAGE    RCDATA    "logo.png" //
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_LOGO_IMAGE), RT_RCDATA);
HGLOBAL hMemory = LoadResource(NULL, hResource);
DWORD imageSize = SizeofResource(NULL, hResource);
void* pImageData = LockResource(hMemory);
// pImageData now points to the PNG file in memory!
  1. Also haven't seen a "www." in a while, might be cleaner to just show thesuperhackers.org.

  2. Maybe also add a Super Hacker Unit soundbite (either random or preselected). Which could dictate the length how long the text is shown on screen. Just for the fact that C&C games do not have dead air.

  3. Maybe consider changing "Game improved by" to something like "Kept alive with love by" or "Lovingly maintained by".

The code itself looks good.


if (TheGlobalData->m_playSizzle)
{
if (TheGlobalData->m_playIntro)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: style, always use braces, several times in this file: line 55, 67, 102, 219, 274

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For small conditions it is generally ok when it reads ok.

@xezon

xezon commented May 26, 2026

Copy link
Copy Markdown
Author

Oh wow why does the ASCII text fall apart like this?

e.displayString->getSize(&pos.x, &pos.y);
pos.x = (screenWidth / 2) - (pos.x / 2);
pos.y = (Int)(e.screenHeightFactor * screenHeight);
e.displayString->setWordWrap(screenWidth);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we set this once? or do we want to do it every frame?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial intent was to make it auto adjust on resolution change during display but that would not work anyway so I moved it now.

{
const DisplaySetting& s = settings[i];
DisplayEntity& e = m_displayEntities[i];
e.sizeX = Int(s.sizeX * fontScale);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is this more general scaling than just font? Maybe uiScale?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed

{
DisplaySetting()
: imageName(nullptr)
, font("Arial")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We set this default but then use Lucida Console everywhere. Maybe just set it here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rationale for this was that the common default font in the game for latin languages is Arial.

@bobtista

Copy link
Copy Markdown

I left some nits, and it needs another rebase, but it looks good to me. I think ESC should work to skip, and/or a -quickstart arg would be nice.

@bobtista

Copy link
Copy Markdown

image image

  1. I don't think ASCII is worth the trouble even though it looks pretty cool.

Maybe something like this:

// logo.h - Generated from logo.png using a tool like xxd or a python script
const unsigned char LOGO_IMAGE_BYTES[] = {
    0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
    // ... thousands of bytes ...
    0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
const unsigned int LOGO_IMAGE_BYTES_LEN = sizeof(LOGO_IMAGE_BYTES);

Embedding an image into the exe is also possible. Some IDE's have resource editors.

// resource.rc
IDB_LOGO_IMAGE    RCDATA    "logo.png" //
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDB_LOGO_IMAGE), RT_RCDATA);
HGLOBAL hMemory = LoadResource(NULL, hResource);
DWORD imageSize = SizeofResource(NULL, hResource);
void* pImageData = LockResource(hMemory);
// pImageData now points to the PNG file in memory!
  1. Also haven't seen a "www." in a while, might be cleaner to just show thesuperhackers.org.
  2. Maybe also add a Super Hacker Unit soundbite (either random or preselected). Which could dictate the length how long the text is shown on screen. Just for the fact that C&C games do not have dead air.
  3. Maybe consider changing "Game improved by" to something like "Kept alive with love by" or "Lovingly maintained by".

The code itself looks good.

Oof that's no good. I'm in favor of using an image instead of ascii. If we need to troubleshoot the ascii, claude says "pick a much larger sizeY (so GDI's full-block glyph actually fills its cell), guarantee the font is installed (or use one shipped with the game), and stop the setWordWrap call from running every draw" - but I still think an image is easier and safer

@xezon xezon force-pushed the xezon/add-new-intro branch from bf25fd5 to 2679b54 Compare May 31, 2026 10:29
@xezon

xezon commented May 31, 2026

Copy link
Copy Markdown
Author
  1. I don't think ASCII is worth the trouble even though it looks pretty cool.

I changed the font. Please try again. A mono font should work. That said, the previous font was supposed to be mono, but maybe it is not on all systems.

  1. Also haven't seen a "www." in a while, might be cleaner to just show thesuperhackers.org.

www. removed.

  1. Maybe also add a Super Hacker Unit soundbite (either random or preselected). Which could dictate the length how long the text is shown on screen. Just for the fact that C&C games do not have dead air.

There is

AudioEvent SuperHackerVoiceCreate
  Sounds = ihassea
  Control = RANDOM
  Priority = HIGH
  Volume = 110.0%
  MinVolume = 100.0%
  Type = WORLD GLOBAL PLAYER
End

I tried triggering it but that did not work, probably because it is a positional sound. Would require more effort to get working.

  1. Maybe consider changing "Game improved by" to something like "Kept alive with love by" or "Lovingly maintained by".

I expect that many players could perceive this as "gay wording", because "lovingly" does not fit the theme of the game.

@xezon xezon requested a review from bobtista May 31, 2026 16:21
@githubawn

Copy link
Copy Markdown
image

It looks even stranger now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Art Is art related Enhancement Is new feature or request Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Refactor Edits the code with insignificant behavior changes, is never user facing ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants