Jump to content

EXE editing & programming issues


MrFlibble

Recommended Posts

IIRC when I ran some tests with the saboteur (in v1.07 but it was some time ago so details are a bit vague), it sometimes (or maybe every time) would run under a unit and stand there instead of destroying it. I am, however, not sure if this would be a friendly unit or an enemy unit (or both). I usually play the game on the fastest speed setting, so this may not apply to normal speed.

Link to comment
Share on other sites

I think it was a coincidence, by my tests the Saboteur with fastest speed gameplay detonates on rock/sand delimiters terrain, or concrete tiles for example, independently on the fact that on the tile there is an Unit (friend or enemy) or not.

On normal speed gameplay, the Saboteur detones always on any tile.

Because of this different odd behaviour, I think that Amiga version it's the best handy choice.

Link to comment
Share on other sites

I think it was a coincidence, by my tests the Saboteur with fastest speed gameplay detonates on rock/sand delimiters terrain, or concrete tiles for example, independently on the fact that on the tile there is an Unit (friend or enemy) or not.
IIRC the units were on plain sand. Friendly or not, I can't remember because I could have used the Stop command to make enemy units passive (so that they do not fire at the Saboteur). The Saboteur would go under the unit (i.e. the unit's graphics would conceal that of the Saboteur and it would become unselectable by mouse clicking unless the unit moved away or by using Tab to cycle through available units.)
Because of this different odd behavour, I think that Amiga version it's the best handy choice.
That is very possible, I think they improved on the DOS v1.07 code for the Amiga port, might have fixed the Saboteur stuff as well.
Link to comment
Share on other sites

The Saboteur would go under the unit (i.e. the unit's graphics would conceal that of the Saboteur and it would become unselectable by mouse clicking unless the unit moved away or by using Tab to cycle through available units.)
Exactly, as shown by my attached youtube video (when I moved the Sabouter under the Troopers).
Link to comment
Share on other sites

-Fix (#166): do not select unit's original location after issuing target.

https://github.com/OpenDUNE/OpenDUNE/pull/166

 

The function we need to change is

void GUI_ChangeSelectionType(uint16 selectionType);

There's a switch statement that looks something like:

switch (oldSelectionType) {    case SELECTIONTYPE_TARGET:    case SELECTIONTYPE_PLACE:        Map_SetSelection(g_structureActivePosition);        /* Fall-through */    case SELECTIONTYPE_STRUCTURE:        g_cursorDefaultSpriteID = 0;        GUI_DisplayText(NULL, -1);        break;        ...}

In the OpenDUNE patch, I simply made the SELECTIONTYPE_TARGET case jump to the SELECTIONTYPE_STRUCTURE code block. This function used to be called f__B4E9_0050_003F_292A. It was converted to C here:

https://github.com/OpenDUNE/OpenDUNE/commit/e6fc7edb83fe169ef61a374551542acd7ba51631

Near l__00BD:

emu_ip = emu_get_memory16(emu_cs, emu_bx, 0x33B);switch (emu_ip) {    case 0x00DA: goto l__00DA; /* case SELECTIONTYPE_TARGET, SELECTIONTYPE_PLACE */    case 0x00E4: goto l__00E4; /* case SELECTIONTYPE_STRUCTURE */    case 0x00FE: goto l__00FE; /* case SELECTIONTYPE_UNIT */    case 0x0133: goto l__0133; /* case SELECTIONTYPE_MENTAT */    default:        /* In case we don't know the call point yet, call the dynamic call */        emu_last_cs = 0xB4E9; emu_last_ip = 0x00D5; emu_last_length = 0x001D; emu_last_c        emu_call();        return;}

Near l__00DA: you find the call to emu_Map_SetSelection.

Near l__00E4: you find the call to emu_GUI_DisplayText.

 

Anyway, it looks like it jumps an offset given by an array indexed by the old selection type. The selection types are:

typedef enum SelectionType {    SELECTIONTYPE_MENTAT    = 0,    SELECTIONTYPE_TARGET    = 1,    SELECTIONTYPE_PLACE     = 2,    SELECTIONTYPE_UNIT      = 3,    SELECTIONTYPE_STRUCTURE = 4,    ...} SelectionType;

I tried to patch up that array:

33 01 DA 00 DA 00 E4 00 FE 00 -> 33 01 FE 00 DA 00 E4 00 FE 00

 

But that doesn't seem to work by itself.  It might be because after issuing the target and just before calling this function, the active unit is set to NULL (see GUI_Widget_Viewport_Click).

  • Upvote 1
Link to comment
Share on other sites

I still haven't figured out what is this code, and where I must search (into EXE or some EMC?).

Where are all parts of code about GUI in Dune 2?

 

Maybe we can start from these bytes:

33 01 DA 00 DA 00 E4 00 FE 00 -> 33 01 FE 00 DA 00 E4 00 FE 00

 

Where can I find them?

Link to comment
Share on other sites

[...]

I tried to patch up that array:

33 01 DA 00 DA 00 E4 00 FE 00 -> 33 01 FE 00 DA 00 E4 00 FE 00

 

But that doesn't seem to work by itself.  It might be because after issuing the target and just before calling this function, the active unit is set to NULL (see GUI_Widget_Viewport_Click).

In v1.07-EU (0x050C2B-0x050C33) I found a similar bytes sequence, I think it's the same thing we are talking about:

 

33 01 da 00 da 00 fe 00 e4 00

 

Looking the case:

case 0x00DA: goto l__00DA; /* case SELECTIONTYPE_TARGET, SELECTIONTYPE_PLACE */case 0x00E4: goto l__00E4; /* case SELECTIONTYPE_STRUCTURE */case 0x00FE: goto l__00FE; /* case SELECTIONTYPE_UNIT */case 0x0133: goto l__0133; /* case SELECTIONTYPE_MENTAT */

 

The right workaround should be:

 

33 01 e4 00 da 00 fe 00 e4 00

 

By my tests so GUI never 'loses' selected units.

  • Upvote 1
Link to comment
Share on other sites

The right workaround should be:

 

33 01 e4 00 da 00 fe 00 e4 00

 

By my tests so GUI never 'loses' selected units.

Super cool, thanks for the fix!

On another note, I've just read a very interesting post:

Hey,

New to the forum; have a question.

Most people who have dabbled with the Dune 2 Demo (the one from Westwood's FTP), know it can easily be made playable, and they also know about the demo-only keys; F7 to subtract from the map seed and reset, F8 to add 1 to the map seed and reset, and L to lift the Fog-of-war. As far as we know these keys were used to find "usable" map seeds.

Anyways, is it too much of a stretch to look into the code of the demo, and perhaps add these keys as a "Developer Mode" or "Enabled advanced keys"? I have found the functions very, very useful when developing new maps, in any case. Using the keys I can see immediately what the map will look like in Dune 2, without having to quit Dune > edit map > save map > restart Dune 2, and so on.

Just a thought.

~ Glossu

[emphasis added]
Link to comment
Share on other sites

Ah, awesome drnovice :)
 
MrFlibble: those debug keys don't exist in OpenDUNE.  The reveal is simple enough to implement in OpenDUNE.  Just call Tile_RemoveFogInRadius with a massive radius.  E.g.

static void InGame_Numpad_Move(uint16 key){    switch (key) {        case 0x0010: /* TAB */            Map_SelectNext(true);            return;         case 0x0110: /* SHIFT TAB */            Map_SelectNext(false);            return;         /* DEBUG: reveal map. */        case something:            Tile_RemoveFogInRadius(Tile_UnpackTile(Tile_PackXY(32,32)), 64);            return;         ... num pad scrolling cases ...    }}

 

Link to comment
Share on other sites

 

Ah, awesome drnovice :)

 

MrFlibble: those debug keys don't exist in OpenDUNE.  The reveal is simple enough to implement in OpenDUNE.  Just call Tile_RemoveFogInRadius with a massive radius.

Actually, I found a beta switch in C&C that simply prevents drawing the shroud. It doesn't bother actually revealing the map. If you ever played Warcraft and messed around with its cheats, it's like the difference between the "showpath" and "on screen" codes. One just shows the map, but the game still acts as if it isn't revealed. The other actually reveals the area.

In C&C, a notable effect of this is that even though everything is visible, helicopters still can't move into unexplored terrain. In Warcraft II, with "showpath", Attack commands given to stuff in unexplored terrain revert to Move commands, just like they would if there was still shroud.

Anyway is the version within Legend of Kyrandia CD, indicated by Nyerguds some time ago?
That one just looped the intro... I doubt there's any beta stuff in it.
Link to comment
Share on other sites

Yes, I found version we were talking about.
Incredibly it works all that indicated.. :P I don't test still a lot, but thanks to segra:

And back on the The Demo EXE, its actually really easy to put in play mode
all that is required is adding *any* command line parameter to it when u start it up :)

dune2 dfgbdgdgsd will work fine :)

will put it in play/record mode, automatically recording to DUNE.LOG.

To completely skip the intro, edit the exe and set the byte at 0x3A108 to 01
 

You can play it and I tried F7-F8 and L Key. Only thing is that when it resets the structures remain but they aren't selectable anymore.

You can even do "Restart the Scenario". Mentant Menu isn't available.

I would like try so:

And to be able to enter the construction yard/other structures to build items, copy the files

choam.cps
choamshp.shp
grayrmap.tbl


from Dune2 1.00 Dynasty (dune.pak), into the demo dir... all works well then ;)

:)

Link to comment
Share on other sites

Temporary reporting.

 

For some strange reason, the OpenDune forum did not accept 'Temporary' as a nick. Anyways, as said, I reported those findings to the OpenDune forum some time ago. I also added some more info there, but to reiterate; by making the demo interactive, you can control all the units and structures, including sandworms (which have a few other surprises in store). There is a ton of stuff to explore in the demo, and if you haven't done so yet, please do. I won't ruin the fun of finding it all out. :)

 

I am somewhat surprised none of this was common knowledge. From what I understand, the map seed keys and the reveal key are remnants from an earlier code base; essentially code left over from in-build functions, functions used to find usable map seeds, to find out how game and unit balancing affects outcomes, among other things. For this, and many other reasons, the demo contains a lot of interesting content.

 

Oh, by the way; pressing 'W' promptly exits the demo via a "Buy our game" message.

 

That's all for now.

  • Upvote 1
Link to comment
Share on other sites

MrFlibble: those debug keys don't exist in OpenDUNE.
Huh? Did I state otherwise anywhere? ???
I am somewhat surprised none of this was common knowledge.
Apparently, none of us here bothered testing the demo extensively. I remember that I compared the data files (there's an insignificant difference in the ICON.ICN/ICON.MAP tile set file) and played the mission a bit, with the enemy units being controllable and such. I also tried playing as the other Houses via the "change current House" trick that Super Dune 2 uses, and checked the Palace superweapons. But I didn't even think of trying to press the F1-F12 keys to find out what would happen.
Link to comment
Share on other sites

There is a ton of stuff to explore in the demo, and if you haven't done so yet, please do. I won't ruin the fun of finding it all out. :)
Actually... I'm one of these people who prefer pooling information rather than just telling people to just do it themselves to find out what's in there... Call me crazy, but, um, it's just more practical. Especially since some people may miss stuff others do find out.
Link to comment
Share on other sites

Nyer's right, we've already missed quite a lot (mostly by simply not knowing where to look, and for what), and it's some general consideration that one cannot possibly try out everything, even in such a small-scale programme as a game demo.

Link to comment
Share on other sites

Hey,
 
Alrighty then, here is some of what I've gathered from the demo. I have more of this stuff in various files on my clogged up hard drive.
 
 
 
Map
 
The map used in the demo is actually reused in the retail Atreides campaign. You may recognize the map from Mission 3 of the campaign, it is in fact the 'middle map' of the three available maps, also known as map 3B. The map proper is provided in two separate files, both as a map file in the packed data file, and as a saved game.
 
The map is not an exact match with the retail version. The retail version has an enemy unit cap set at 20 units, whereas the demo version has the Harkonnen unit cap set at 16 units. The demo game engine disregards the unit cap however, rendering it meaningless.
 
As you may recognize this map from the retail campaign, you may also realize how little effort was put into creating the maps; all the scenario bugs that were shipped with retail—and there are many—were seemingly firmly in place 6 months before the game shipped.
 
 
 
Keys
 
Since the demo version allows control over the enemy units and enemy structures, certain additional keys have special functions. These serve no purpose in the retail version.
 
Key Function Notes
R Area guard Places enemy units in Area guard mode (only when controlling enemies).
A Ambush Places enemy units in Ambush mode (only when controlling enemies).
G Guard Places enemy units in Guard mode (only when controlling enemies).
H Hunt Places enemy units in Hunt mode (only when controlling enemies).
W Exit demo Displays a banner prompting the player to purchase the retail version and terminates.
R Cycle messagesStep forwards in message queue (only when not controlling any unit, after F7/F8).
T Cycle messages Step backwards in message queue (only works after pressing the F7 and F8 keys)
L Reveal map Completely removes the Fog-of-war, revealing the map.
[esc] Pauses game Simply pauses the game (why this wasn't kept for retail is anybody's guess).
[period] Place special bloom Places a special bloom in the position of the unit (must be on sand).
[hyphen] Place spice bloom Places a spice bloom in the position of the unit (must be on sand).
[insert] Add credits Each press of the insert key adds 1000 credits of spice to the player.
F3 Rotate unit Rotate unit anti-clockwise, also affects heading when moving (only when controlling units).
F4 Rotate unit Rotate unit clockwise, also affects heading when moving (only when controlling units).
F5 Rotate turret Rotate turret of active unit anti-clockwise (only when controlling tanks or siege tanks).
F6 Rotate turret Rotate turret of active unit clockwise (only works with tanks or siege tanks).
F7 Reseed the map Subtracts the seed by 1 and resets the map, including the Fog-of-war.
F8 Reseed the map Adds 1 to the map seed and restarts the map, resetting the Fog-of-war.
 
 
The below keys are for the Structure and Unit Placement tool only
 
House keys are:
  • Shift for Ordos
  • Ctrl for Harkonnen
  • Alt for Atreides
  • Shift + Ctrl for Mercenary
  • Alt + Shit for Sardaukar
  • Ctrl + Alt for Fremen
 
[House key]+1 Place harvester
[House key]+2 Place infantry
[House key]+3 Place trooper
[House key]+4 Place MCV
[House key]+5 Place sandworm (the sandworm is always Fremen)
[House key]+6 Place devastator
[House key]+7 Place saboteur
[House key]+F3 Place trike
[House key]+F4 Place quad
[House key]+F5 Place tank
[House key]+F6 Place siege tank
[House key]+F7 Place launcher
[House key]+F8 Launch carryall
[House key]+F9 Launch ornithopter
[House key]+F10 Place sonic tank
[House key]+E Place windtrap
[House key]+R Place repair facility
[House key]+T Place turret
[House key]+U Place rocket turret
[House key]+I Place House of Ix
[House key]+O Place radar outpost
[House key]+P Place palace
[House key]+A Place concrete slab
[House key]+S Place starport
[House key]+D Place wall (must be placed on slabs)
[House key]+F Place refinery
[House key]+G Place hi-tech facility
[House key]+H Place heavy factory
[House key]+K Place large concrete slab
[House key]+L Place light vehicle factory
[House key]+C Place construction yard
[House key]+B Place barracks
 

Note you cannot place a WOR facility.

 
 
 
Differences and peculiarities
 
There are obviously several differences between the demo and the retail versions of the game. These are due to several reasons. The first reason is the demo version precedes the retail version and must be seen as a work-in-progress. The other obvious reason for the peculiar behavior is due to the demo not being meant to be playable. Thus one of the main differences is the demo is not nearly as stable as the retail version. The demo is known to spontaneously freeze, to unexpectedly terminate, to lock the keyboard, and so on. These differences are obviously invisible to the player.
 
The first differences player most often notice, however, are the colors of the mini map, i.e. the radar screen. In the retail version, the spice fields are a brownish hue. In the demo the fields are a festive pink.
 
Another difference that the player soon notices is the massive speed increase the harvesting has in the demo. The harvesters fill up quickly, sometimes up three times faster than they do in retail. Trying to access the Mentat screen by either pressing F1 or by clicking the 'Mentat' button will only produce a message stating the demo is indeed what is supposed to be--merely a demonstration program--and that the Mentat advisor is therefore unavailable. What is most peculiar about this is that the Mentat message should never even be accessed; without hacking the demo and making it playable the message cannot be seen, it should simply never possible to even get the message.
 
There are other instances that are equally perplexing. By providing the three missing files and by making the demo interactive, the player can open the construction window of the buildings. When doing so a message will inform the player detailed pictures are not available in the demonstration program.
 
This is yet another message that should never be available to the player. Without hacking the demo the message can never be seen. This same error message can be seen in all the production windows of all buildings that can produce either units or more buildings. Note the production screen for enemy structures cannot be accessed; clicking on the structure icon or pressing F3 has no effect whatsoever. Also note the higher resolution images are not supplied with the demo.
 
As a further peculiarity, the demo sometimes displays messages to the player using the internal strings as names for the structures and units, and not the long form names as it is supposed to. The user interface was not yet polished at this point; the demo must for all intents and purposes be seen as a work-in-progress. Of note is also the different tech tree. The map is supposedly one of the three maps in the third mission of the Atreides campaign, yet the tech tree seems to be the same as the tech tree of mission four.
 
As the demo is a work in progress, the game play is still littered with bugs, and the game is in a much unfinished state. Destroying enemy turrets will not replace the turrets with rock, as should happen, but the turrets will instead be replaced by the upper right corner of the spice silo. This is a graphical glitch only, the terrain is still considered rock by the game engine.
 
 
 
Controlling the enemy
 
The perhaps most fascinating aspect of the demo is it gives the player almost complete control of the enemy forces and the enemy's activities. The player can issue orders to and control every enemy unit, including enemy harvesters. The player can also stop enemy unit production, disengage repairs, halt advancing armies, and make AI credits completely dry up.
 
In addition to making the demo ridiculously easy and unchallenging to play, by monitoring the enemy units the player can gain insights into how the Computer-controlled forces operate, and how the AI spends and manages its resources.
 
The simplest way to immediately cripple the AI is to simply stop the enemy harvesters from harvesting spice. There can be no simpler way to achieve this; simply click the enemy harvester, and click the 'stop' button. The harvester will remain stationary until told otherwise. The AI will now slowly but surely run out of spice and thus credits. The player can even move the enemy harvester to another location, for example into the mouth of the Fremen sandworms that roam the map. Doing so will not provide the enemy with a brand new harvester, in contrast with the retail version.
 
In the demo the sandworm is explicitly mentioned as belonging to the Fremen. While it is mentioned in the books and the movie that the Fremen and sandworms have a profound relationship, it is never made explicit in the retail game. Internally the sandworms are obviously Fremen, but the player never sees this during game play. Other differences include the ability of the sandworms to detonate spice blooms.
 
In addition to this, the sandworm has a completely different set of commands in the demo, as compared to the command set in the retail version of the game. In the retail version, the sandworm only has an attack command. In fact it has four of them.
 
Game maps can be edited in the retail version to give the player control over the sandworms, but even if the player has a semblance of control over the worms, the massive Shai-Hulud remain semi-autonomous - devouring player units, spontaneously attacking its own faction, and so on. In the demo, the sandworms can be given the standard set of commands available for the Computer-controlled units. Under certain circumstances, the sandworm can even be told to retreat. As mentioned, in retail Dune player-controlled sandworms can only attack. This might actually reflect their nature fairly accurately. In another departure from the retail version, sandworms in the demo disappear after devouring one unit. Sandworms can also detonate blooms of any kind. They can even attack each other.
 
The player has almost total control of the enemy units. While the command set lacks the possibilities to stop and specifically move the units, rather complex unit movement can be achieved. To stop approaching enemy units, simply click on the unit and click the 'guard' button. This will place the enemy unit in guard mode, effectively stopping it.
 
If the enemy units have already entered your base, you can send them back to their point of origin by clicking the unit and clicking the 'area guard' button. Since the unit's point of origin is the enemy base, the unit will simply retreat to the enemy base and possibly begin its attack again. Repeat as necessary.
 
It is theoretically possible to place the enemy units in ambush mode by clicking the 'ambush' button, but since an enemy unit must be visible in order to be controlled, ambush mode will immediately revert to hunt mode. So, while this should be theoretically possible, it is a logical impossibility.
 
The player can even control enemy structures, albeit in a limited fashion. The player can interrupt ongoing repairs by simply clicking the 'repair' button. The player can also put unit production on hold indefinitely. The AI will in certain circumstances restart repairs, but unit production will remain on hold until manually restarted by the player, or until the game ends. The player can even upgrade enemy structures, although the AI will do so itself immediately when it has the necessary funds. While 'helping the AI along' is theoretically possible, it is of very limited application.
 
Trying to control enemy palaces will result in the demo crashing. The only palace super weapon that works seems to be the Death Hand missiles. Also, the player can launch three consecutive Death Hand missile attacks from the palace, with no recharging time in between. However after the attacks have been launched, the demo will not give control back to the player, even after restarting the scenario. The demo will display the palace control panel indefinitely.
 
By monitoring the enemy units and the enemy base, it is easy to get an insight into the AI strategy. The demo is not an exact copy of the retail version; there are major differences. When an enemy structure is destroyed, the AI is rewarded credits in the form of spice; the amount of credits is half the cost of the destroyed structure. Since the AI only pays 50% of the normal price when constructing a building, the AI can theoretically replace any destroyed structures indefinitely. This cycle can easily be stopped by halting the enemy harvesters and putting all construction on hold.
 
 
 
End of map
 
When the demo map comes to an end - either through loss or victory, or by pressing the W key - the player will only see a prompt message, urging the player to order the soon-to-be-released retail version, or to look for the game at well equipped game retailers.
 
When the map ends there is no tallying of the scores, no rank is awarded, and no statistics are displayed. In fact, there exists neither graphics nor data files anywhere in the packed files for the rank display and high score entry panels. After the prompt message has been displayed, the demo will terminate and exit to the MS-DOS prompt, or back to Windows if the demo is played in a box, without any further prompts.
 
The demo map is a version of Atreides map 3B, the main difference being the lesser unit cap for the Harkonnen. However, the demo completely disregards the unit cap, making this a difference without distinction.
 
If the player attempts to challenge fate, and clicks on the 'Pick another house' option from the in-game menu, the demo will inform the player there are in fact no other scenarios, wait a while, and terminate, exiting to the MS-DOS prompt without further ado.
 
The map itself is unique to the demo, and it is provided in several places; inside the DUNE.PAK file, as part of the saved game, and as the provided dune.log file.
 
 
 
Special demo keys
 
There are functions in the demo that cannot be found in any subsequent installment of the game. The most tantalizing is the map reseeding function. By pressing the keys F7 and F8 the player can change the seed of the map, and reset the map to its initial state. This will of course also reset the Fog-of-war, setting the map black. Only units and buildings will be visible. When reseeding and resetting the map, the player will lose control of most of the buildings; all buildings will be stripped of their ownership bit, except the spice refinery. Due to this the buildings - except the refinery - will have no owner and can no longer be controlled. The buildings will be regarded as terrain by the game engine. Erecting a new CY with an MCV, upgrading and then constructing a large concrete slab will return control to the player. The slab needs not be placed, only constructing it will return control of the buildings. The function is rather unstable and can produce unexpected results.
 
In addition, reseeding and resetting the map will corrupt the map data; two, sometimes four rectangular pieces of mountains will run along the southern edge of the map. The terrain will have the same function as mountains; carryalls, ornithopters, and frigates can fly over it, and infantry units can traverse it. Saving and re-loading the game will not reset the map; the corrupt data will remain.
 
The Fog-of-war can be completely lifted by pressing the L key. This does not reveal the mini map unless you have a radar outpost. When used together with the reseeding keys, the player can quickly cycle forwards and backwards in the seed queue; lifting the Fog-of-war will immediately show if the new map can be used as a scenario map. The theory is these special demo keys were used by the developers when trying to find usable map seeds.
 
If you are going to use the L key when playing a custom scenario, be advised all enemy units placed in ambush will immediately revert to hunt mode when they become visible.
 
Also, when placing the blooms - special blooms or spice blooms - be advised the blooms will be placed on the current active position. Sometimes this means the square where the unit is heading. This means the bloom will be placed in front of the unit and immediately activated. If the bloom placed is a spice bloom, you will lose the unit.
 
Pressing the 'insert' key will add credits to the House which is being controlled; if it is the player's House, the House gets 1000 credits. If it is the Computer-controlled House, the House gets 500 credits.
 
 
Pressing the function keys F5 to F10 while holding the Alt key places various Atreides units in the current, active location. In sequence the units are tank, siege tank, launcher, carryall, ornithopter, and sonic tank. The tanks or the launcher will only be placed if the player is controlling an enemy infantry unit while pressing the keys. The flying units will appear from any controlled location, even from sandworms.
 
Please be advised any Atreides ornithopters will attack any other House, without prejudice. This might include the player's units; if the House of the player is any other than Atreides, the spawned ornithopters will attack the player's units. In addition, ornithopters spontaneously self-destruct in the demo.
 
When placing structures, please notice you can place the structures according to certain restrictions. If the player's House is one of Atreides, Ordos, or Harkonnen, normal game play restrictions apply. If the player's House is Mercenaries, structures can be placed anywhere. Also note there is (strangely) no way to place WOR facilities with the placement tool.
 
When placing a construction yard, you must hold the keys [House key]+C and click where you want the structure. Construction yards do not need to be connected to anything when they are placed.
 
To place structures of any other house, instead of the Alt key press Ctrl for Harkonnen, Shift for Ordos, Ctrl+Shift for Mercenaries, Alt+Ctrl for Sardaukar, and Alt+Shift for Fremen.
 
 
The log file
 
When the un-hacked demo is started normally, it will auto-replay the ending of a scenario, show a prompt asking the viewer to pre-order the game, wait for a few seconds, and then exit. The replay is contained in the log file provided with the downloadable demo.
 
When the demo is started with any parameter, the log file is disregarded; the demo enters its interactive mode, and the player can control the game. When this is done, the log file is overwritten with a new log file. This log file is then replayed when the demo is started without parameters.
 
The log file replay will begin at the point of game entry; if a saved game is loaded, the replay will start at the load point. If the map is played from start to finish in one go, the log file will contain the entire game play.
 
Be advised there is no real size limit to the log file; the only limit is the ability of the game code to write a file to disk. Since the game is a 16-bit game, the log file can be 2 gigabytes in size.
 
 
 
Unit and building specifications
 
The unit and building specifications in the demo are essentially identical to the initial retail version - version 1.0 - with a few minor differences.
 
The unit and structure hit points are identical.
 
Weapons damage is almost identical, with the difference being more damaging sonic tanks in the demo; the sonic tank deals 75 points of damage in the demo, whereas the retail version is slightly tamer, with only 65 points of damage. The sonic blast itself is doubly as lethal in the demo, with 50 points in the demo compared to 25 in retail.
 
House Atreides is just as susceptible for structural damage as all the other Houses in the demo.
 
House Harkonnen is even easier to deviate in the demo; the demo has an 89% success rate set, whereas the retail has lowered the Harkonnen deviation success rate to 78%.
 
Costs are slightly different. Repair facilities cost 900 credits in the demo, as opposed to 700 in retail. Since the hard coded tech tree never allows repair facilities to be built this is a difference without distinction. Walls cost 60 credits in the demo, whereas they only cost 50 in retail.
 
The Ordos' special weapon is somewhat crippled in the demo; the recharge time is double that of retail. The Ordos' saboteur is also significantly slower in the demo; moving at half the speed.
 
As a final curiosity, none of unplayable Houses - Fremen, Sardaukar, or Mercenaries - have a special palace weapon in the demo. Thus their palace recharge time is also set to zero.
 
When compared to the last version of the game - version 1.07 - the actual differences are trivial - frigates have 500 hit points instead of 100, ornithopters have 10 hit points instead of 25 - and have very little impact on game play.
 
 
 
Looping demo
 
The looping demo cannot be made playable. The looping demo is - while simpler - in fact a later creation, based on the last patched version of the game; version 1.07. It must be seen as the historically last official Dune 2 offering by Westwood, demo or otherwise.
 
 
I hope this helps.
 
~ Temporary
  • Upvote 3
Link to comment
Share on other sites

Temporary, thanks for such an extensive analysis of the demo's functionality! :)

Looping demo

 

The looping demo cannot be made playable. The looping demo is—while simpler—in fact a later creation, based on the last patched version of the game; version 1.07. It must be seen as the historically last official Dune 2 offering by Westwood, demo or otherwise.

I'm pretty certain that the demo EXE can be hacked to revert it back to the playable state, since it seems to have everything in terms of code etc. The question here is whether that EXE has anything new gameplay-wise compared to the EU version.

Link to comment
Share on other sites

Hey,

 

Thank you for the video, Dr. Novice. Yes, some of the things I posted are easier to understand when one can actually watch it happening.

 

Note that it is possible to drive units into buildings when controlling them and pressing F3/F4 when close to a building (you will lose most units when they are swallowed by the structure). Just have a unit drive past a building with a move command, and turn it so it heads into the structure. Also note that a refinery will "spit out" the offending unit, whereas other buildings will not. (I am still riffling through some of my age-old documentation regarding Dune 2, so these info tidbits might come in drips and drabs, sorry 'bout that.)

 

The demo is a strange beast, indeed.

 

(These posts can surely be lopped off this thread and placed in a thread of it's own.)

Link to comment
Share on other sites

Talking about Timeout Win/Lose Flags:

TrueBrain said:I couldn't find any reference that this was indeed figured out. So I just wanted to let you know. Sorry to dig up this old topic, I hope that is okay.

First of all, those are bit-fields. Their meaning (same for both):

1 -> Enemy has no buildings
2 -> You have no buildings
4 -> You reached credit quota
8 -> You reached time limit

That was the easy part. The scenarios also tempt to use 16 as flag, but that seems never used.

Now, the meaning of those 2 flags. First, forget about the name, they are very misleading. What they mean:

WinFlags -> Conditions to be met for the game to end (win or lose!).
LoseFlags -> Conditions to be met to win the game.

So, if we take any campaign 2 level (when using MrFlibbles scenario.pak, else one of the Atreides campaigns is broken):

WinFlags -> 7
LoseFlags -> 5

So the game ends if: you have no buildings, the enemy has no buildings, or you reached the credit quota.
You will win the level if: the enemy has no buildings, or you reached the credit quota.
You will lose the level if: you have no buildings. (derived from disabling the bits in WinFlags that are active in LoseFlags).

And that is all there is to it. So the names are very misleading, but the result is very simple (and efficient).

(source: http://forum.opendune.org/viewtopic.php?f=13&t=41 )

I managed Timeout victory condition, by my tests it's possible create a Survival Scenario mode (to resist for indicated time) or a mode to destroy the enemy within a specified time. :)
For 1st mode you can set LoseFlags=9 (you win if you reach stipulated time or if you destroy all enemy buildings) and WinFlags=11 (game ends if you or enemy has no more structures OR if stipulated time is reached).
For 2nd mode you can set LoseFlags=1 (to win you must only destroy all enemy buildings) and again WinFlags=11 (like above). So if you haven't destroyed all enemy buildings and stipulated time is reached, the game ends but you lose anyway! :)

TrueBrain said:I don't really get what you mean by this?

Credit Quota means that if flag 4 is set, and the player reaches an amount of credits, the goal is reached.
TimeOut means that if flag 8 is set, and the player plays for N time, the goal is reached (depending on LoseFlag this can be a good thing. Survive N minutes is possible).

The problem with the whole Timeout stuff is: it is partly done (as bluehappybyte already states). The TimeOut value is, as the Quota value, stored in the House information, but never moved to the global variable where it is expected. So all I can tell is that the value always remains 0. I guess it is easy to resolve this issue.

One other thing that really doesn't make sense to me: the check to see if the level ends with the timeout, looks like this (pseudo-code):

if currentTime < variable: level-ends

This doesn't make sense. I can't give any meaning to the 'variable' value which would make sense in this situation. It really feels like they made a bug here, and never fixed it or what ever.

Btw, if we would fix both problems, you could even make a 'survive' map, where you have to hold out for N minutes :)

C++ code responsible about it is (within WinFlags function i.e. GameLoop_IsLevelFinished):

  /* Check for reaching timeout */    if ((g_scenario.winFlags & 0x8) != 0) {        /* XXX -- This code was with '<' instead of '>=', which makes         *  no sense. As it is unused, who knows what the intentions         *  were. This at least makes it sensible. */        if (g_timerGame >= s_tickGameTimeout) {            finish = true;        }    }

and (within LoseFlags function i.e. GameLoop_IsLevelWon):

     /* Check for reaching timeout */     if (!win && (g_scenario.loseFlags & 0x8) != 0)     { win = (g_timerGame < s_tickGameTimeout); }

As explained by the comment, the original code was '<' on both cases.
I found corresponding chunk of code (v1.07-EU) on asm here (WinFlags function):

seg023:0143                   loc_22373:                                                  ; CODE XREF: gameCheckWin+FB j
seg023:0143                                                                               ; gameCheckWin:loc_2233F j ...
seg023:0143 F7 06 01 8D 08 00                 test    mapSettingFlagsWin, 8               ; Logical Compare
seg023:0149 74 39                             jz      short loc_223B4                     ; Jump if Zero (ZF=1)
seg023:014B A1 B2 76                          mov     ax, word ptr timer_1+2
seg023:014E 8B 16 B0 76                       mov     dx, word ptr timer_1

seg023:0152 3B 06 BA 38                       cmp     ax, word_46CCE                      ; Compare Two Operands
seg023:0156 7F 0D                             jg      short loc_22395                     ; Jump if Greater (ZF=0 & SF=OF)
seg023:0158
seg023:0158                   loc_22388:                                                  ; Jump if Less (SF!=OF)
seg023:0158 7C 06                             jl      short loc_22390

seg023:014B A1 B1 76                          mov     ax, word ptr timer_1+1
seg023:014E 8B 16 AC 38                       mov     dx, word_46CC0
seg023:0152 8A D6                             mov     dl, dh
seg023:0156 8B 0E AE 38                       mov     cx, word_46CC2
seg023:0158
seg023:0158                   loc_22388:
seg023:0158 8A F1                             mov     dh, cl
seg023:0158 2B C2                             sub     ax, dx                              ; Integer Subtraction

seg023:015A
seg023:015A                   loc_2238A:                                                  ; Compare Two Operands

seg023:015A 3B 16 B8 38                       cmp     dx, word_46CCC
seg023:015A 3B 06 0B 8D                       cmp     ax, mapSettingTimeout

seg023:015E
seg023:015E                   loc_2238E:                                                  ; Jump if Not Below (CF=0)
seg023:015E 73 05                             jnb     short loc_22395

seg023:015E                   loc_2238E:                                                  ; Jump if Below or Equal (CF=1 | ZF=1)

seg023:015E 76 05                             jbe     short loc_22395

seg023:0160
seg023:0160                   loc_22390:                                                  ; CODE XREF: gameCheckWin:loc_22388 j
seg023:0160 B8 01 00                          mov     ax, 1
seg023:0163
seg023:0163                   loc_22393:                                                  ; Jump
seg023:0163 EB 02                             jmp     short loc_22397
seg023:0165                   ; ---------------------------------------------------------------------------
seg023:0165
seg023:0165                   loc_22395:                                                  ; CODE XREF: gameCheckWin+149 j
seg023:0165                                                                               ; gameCheckWin:loc_2238E j
seg023:0165 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg023:0167
seg023:0167                   loc_22397:                                                  ; CODE XREF: gameCheckWin:loc_22393 j
seg023:0167 0B F0                             or      si, ax                              ; Logical Inclusive OR
seg023:0169 0B F6                             or      si, si                              ; Logical Inclusive OR
seg023:016B 74
15                             jz      short loc_223B4                     ; Jump if Zero (ZF=1)
seg023:016D B8 02 00                          mov     ax, 2
seg023:0170 50                                push    ax
seg023:0171 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg023:0173 50                                push    ax
seg023:0174 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg023:0176
seg023:0176                   loc_223A6:
seg023:0176 50                                push    ax
seg023:0177 1E                                push    ds
seg023:0178 B8 BC 60                          mov     ax, offset aTimeoutWin_             ; "Timeout win."
seg023:017B 50                                push    ax
seg023:017C
seg023:017C                   loc_223AC:                                                  ; Call Procedure
seg023:017C 9A 83 01 23 39                    call    gameWon
seg023:0181
seg023:0181                   loc_223B1:                                                  ; Add
seg023:0181 83 C4 0A                          add     sp, 0Ah
seg023:0184
seg023:0184                   loc_223B4:                                                  ; CODE XREF: gameCheckWin+13C j
seg023:0184                                                                               ; gameCheckWin+15E j
seg023:0184 8B C6                             mov     ax, si
seg023:0186
seg023:0186                   loc_223B6:                                                  ; Jump
seg023:0186 E9 AF FE                          jmp     loc_22268


and here (LoseFlags function):

seg023:0278                   loc_224A8:                                                  ; CODE XREF: gameCheckLose+C5 j
seg023:0278                                                                               ; gameCheckLose:loc_22488 j ...
seg023:0278 F7 06 03 8D 08 00                 test    mapSettingFlagsLose, 8              ; Logical Compare
seg023:027E 74 1E                             jz      short loc_224CE                     ; Jump if Zero (ZF=1)
seg023:0280
seg023:0280                   loc_224B0:
seg023:0280 A1 B2 76                          mov     ax, word ptr timer_1+2
seg023:0283
seg023:0283                   loc_224B3:
seg023:0283 8B 16 B0 76                       mov     dx, word ptr timer_1
seg023:0287
seg023:0287                   loc_224B7:                                                  ; Compare Two Operands

seg023:0287 3B 06 BA 38                       cmp     ax, word_46CCE
seg023:028B 7F 0D                             jg      short loc_224CA                     ; Jump if Greater (ZF=0 & SF=OF)
seg023:028D 7C 06                             jl      short loc_224C5                     ; Jump if Less (SF!=OF)

seg023:0280 A1 B1 76                          mov     ax, word ptr timer_1+1
seg023:0283
seg023:0283                   loc_224B3:
seg023:0283 8B 16 AC 38                       mov     dx, word_46CC0
seg023:0287
seg023:0287                   loc_224B7:
seg023:0287 8A D6                             mov     dl, dh
seg023:028B 8B 0E AE 38                       mov     cx, word_46CC2
seg023:028D 8A F1                             mov     dh, cl
seg023:028D 2B C2                             sub     ax, dx                              ; Integer Subtraction

seg023:028F
seg023:028F                   loc_224BF:                                                  ; Compare Two Operands

seg023:028F 3B 16 B8 38                       cmp     dx, word_46CCC
seg023:028F 3B 06 0B 8D                       cmp     ax, mapSettingTimeout

seg023:0293 73 05                             jnb     short loc_224CA                     ; Jump if Not Below (CF=0)
seg023:0293 76 05                             jbe     short loc_224CA                     ; Jump if Below or Equal (CF=1 | ZF=1)

seg023:0295
seg023:0295                   loc_224C5:                                                  ; CODE XREF: gameCheckLose+FE j
seg023:0295 B8 01 00                          mov     ax, 1
seg023:0298 EB 02                             jmp     short loc_224CC                     ; Jump
seg023:029A                   ; ---------------------------------------------------------------------------
seg023:029A
seg023:029A                   loc_224CA:                                                  ; CODE XREF: gameCheckLose+FC j
seg023:029A                                                                               ; gameCheckLose+104 j
seg023:029A 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg023:029C
seg023:029C                   loc_224CC:                                                  ; CODE XREF: gameCheckLose+109 j
seg023:029C 23 F0                             and     si, ax                              ; Logical AND
seg023:029E
seg023:029E                   loc_224CE:                                                  ; CODE XREF: gameCheckLose+EF j
seg023:029E 8B C6                             mov     ax, si

seg023:02A0
seg023:02A0                   loc_224D0:                                                  ; Jump
seg023:02A0 E9 FE FE                          jmp     loc_223D1

 

Search for:
                     a1 b2 76 8b 16 b0 76 3b 06
ba 38 7f 0d 7c 06 3b 16 b8 38 73 05 b8 01 00 eb
02 33 c0 0b f0 0b f6 74 17 b8 02 00 50 33 c0 50
33 c0 50


Replace with:
                     a1 b1 76 8b 16 ac 38 8a d6
8b 0e ae 38 8a f1 2b c2 3b 06 0b 8d 76 05 b8 01
00 eb 02 33 c0 0b f0 0b f6 74 15 b8 02 00 50 33
c0 50 50


+

Search for:
                                    a1 b2 76 8b
16 b0 76 3b 06 ba 38 7f 0d 7c 06 3b 16 b8 38 73
05 b8 01 00 eb 02 33 c0 23 f0 8b c6


Replace with:
                                    a1 b1 76 8b
16 ac 38 8a d6 8b 0e ae 38 8a f1 2b c2 3b 06 0b
8d 76 05 b8 01 00 eb 02 33 c0 23 f0



As explained by TrueBrain, original code checks the compare (cmp) with not-valued variables (yellow): word_46CCE and word_46CCC. These variables aren't set anywhere, so they remain to 0.
I nopED the checks jg & jl because I think that they are useless, and key value is on dx register (timer_1). I don't undestand what is timer_1+2 offset.
So I changed one of these un-valued word with mapSettingTimeout (seg023:015A & seg023:028F) that is set by INI Scenario file value regards Timeout and checking jb instead jnb, ax is set to 1 when dx register (timer_1) is equal/greater than mapSettingTimeout (Timeout key on INI Scenario file).
At last, I changed Logical AND operator with mov (seg023:029C) to assign updated value to si register, otherwise ax register was always reset to 0 by and operator.

EDITED: Thanks to Dynasty's indication, timer_1 variable contains time (in tick: 1/60 of second) of all game since Dune2.exe is loaded, so to start to count from Scenario real Start, you must subtract word_46CC0 that contains low 16 bit of time point from timer_1 value when Scenario is loaded.

EDITED 2: In orange changes about shift logical right to divide to 16 result of check relative to timeout: so max timeout value (FFFFh or 65535 decimal) takes near 5 hours (nearly 288 mins) as max timeout. Obviously now you must divide to 16 value of tickValue into Scenario INI file to obtain correct result (e.g. to set 3 minutes => 60*60*3=10800 / 16 = 675)

EDITED 3: Last change -> g_timerGame (timer_1+2 & timer_1) and g_tickScenarioStart (word_46CC2 & word_46CC0) are uint32, instead g_scenario.timeOut (mapSettingTimeout) is uint16.
There wasn't enough room to compare both 2 registers (low 16 bits & high 16 bits) for these values, and then to make subtraction between them, so I took CENTRAL 16 bits of 2 registers (00000000|11111111 & 11111111|00000000) to compare (after subtraction) with uint16 mapSettingTimeout value.
As suggested by Dynasty, value to write into Scenario INI files is (60*60)/256 (because first 8 bits are discarded being them less significant) to obtain 1 minute, i.e. tick number unit (60*60) divided by 256 (2^8 or 28).
E.g. to have a timeout of 20 mins: 14 * 20 = 280 -> TimeOut=280 into Scenario INI file.

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...